Browse Source

created description field in user profile

Andrzej Zadrozny 6 years ago
parent
commit
ec7f296253

+ 44 - 48
api/pb/auth.pb.go

@@ -3,13 +3,14 @@
 
 package pb
 
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
 import (
-	context "context"
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	_ "google.golang.org/genproto/googleapis/api/annotations"
+	context "golang.org/x/net/context"
 	grpc "google.golang.org/grpc"
-	math "math"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -21,7 +22,7 @@ var _ = math.Inf
 // is compatible with the proto package it is being compiled against.
 // A compilation error at this line likely means your copy of the
 // proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 type AuthStatusRequest struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -33,17 +34,16 @@ func (m *AuthStatusRequest) Reset()         { *m = AuthStatusRequest{} }
 func (m *AuthStatusRequest) String() string { return proto.CompactTextString(m) }
 func (*AuthStatusRequest) ProtoMessage()    {}
 func (*AuthStatusRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8bbd6f3875b0e874, []int{0}
+	return fileDescriptor_auth_5d9157b05cb925f8, []int{0}
 }
-
 func (m *AuthStatusRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_AuthStatusRequest.Unmarshal(m, b)
 }
 func (m *AuthStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_AuthStatusRequest.Marshal(b, m, deterministic)
 }
-func (m *AuthStatusRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_AuthStatusRequest.Merge(m, src)
+func (dst *AuthStatusRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AuthStatusRequest.Merge(dst, src)
 }
 func (m *AuthStatusRequest) XXX_Size() int {
 	return xxx_messageInfo_AuthStatusRequest.Size(m)
@@ -66,17 +66,16 @@ func (m *AuthAuthenticateRequest) Reset()         { *m = AuthAuthenticateRequest
 func (m *AuthAuthenticateRequest) String() string { return proto.CompactTextString(m) }
 func (*AuthAuthenticateRequest) ProtoMessage()    {}
 func (*AuthAuthenticateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8bbd6f3875b0e874, []int{1}
+	return fileDescriptor_auth_5d9157b05cb925f8, []int{1}
 }
-
 func (m *AuthAuthenticateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_AuthAuthenticateRequest.Unmarshal(m, b)
 }
 func (m *AuthAuthenticateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_AuthAuthenticateRequest.Marshal(b, m, deterministic)
 }
-func (m *AuthAuthenticateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_AuthAuthenticateRequest.Merge(m, src)
+func (dst *AuthAuthenticateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AuthAuthenticateRequest.Merge(dst, src)
 }
 func (m *AuthAuthenticateRequest) XXX_Size() int {
 	return xxx_messageInfo_AuthAuthenticateRequest.Size(m)
@@ -113,17 +112,16 @@ func (m *AuthStatusResponse) Reset()         { *m = AuthStatusResponse{} }
 func (m *AuthStatusResponse) String() string { return proto.CompactTextString(m) }
 func (*AuthStatusResponse) ProtoMessage()    {}
 func (*AuthStatusResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8bbd6f3875b0e874, []int{2}
+	return fileDescriptor_auth_5d9157b05cb925f8, []int{2}
 }
-
 func (m *AuthStatusResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_AuthStatusResponse.Unmarshal(m, b)
 }
 func (m *AuthStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_AuthStatusResponse.Marshal(b, m, deterministic)
 }
-func (m *AuthStatusResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_AuthStatusResponse.Merge(m, src)
+func (dst *AuthStatusResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AuthStatusResponse.Merge(dst, src)
 }
 func (m *AuthStatusResponse) XXX_Size() int {
 	return xxx_messageInfo_AuthStatusResponse.Size(m)
@@ -159,17 +157,16 @@ func (m *AuthAuthenticateResponse) Reset()         { *m = AuthAuthenticateRespon
 func (m *AuthAuthenticateResponse) String() string { return proto.CompactTextString(m) }
 func (*AuthAuthenticateResponse) ProtoMessage()    {}
 func (*AuthAuthenticateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8bbd6f3875b0e874, []int{3}
+	return fileDescriptor_auth_5d9157b05cb925f8, []int{3}
 }
-
 func (m *AuthAuthenticateResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_AuthAuthenticateResponse.Unmarshal(m, b)
 }
 func (m *AuthAuthenticateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_AuthAuthenticateResponse.Marshal(b, m, deterministic)
 }
-func (m *AuthAuthenticateResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_AuthAuthenticateResponse.Merge(m, src)
+func (dst *AuthAuthenticateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AuthAuthenticateResponse.Merge(dst, src)
 }
 func (m *AuthAuthenticateResponse) XXX_Size() int {
 	return xxx_messageInfo_AuthAuthenticateResponse.Size(m)
@@ -194,32 +191,6 @@ func init() {
 	proto.RegisterType((*AuthAuthenticateResponse)(nil), "pb.AuthAuthenticateResponse")
 }
 
-func init() { proto.RegisterFile("auth.proto", fileDescriptor_8bbd6f3875b0e874) }
-
-var fileDescriptor_8bbd6f3875b0e874 = []byte{
-	// 306 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x51, 0x41, 0x4e, 0x2a, 0x41,
-	0x10, 0xcd, 0x90, 0xff, 0x11, 0x0b, 0x37, 0x36, 0x22, 0x38, 0x10, 0x63, 0x26, 0x2e, 0xd4, 0x05,
-	0xa3, 0xb8, 0x73, 0xe7, 0x11, 0x1c, 0x35, 0x71, 0x67, 0x1a, 0xac, 0xc0, 0x44, 0xed, 0x1a, 0xbb,
-	0x6a, 0x70, 0xef, 0x15, 0x3c, 0x9a, 0x1e, 0xc1, 0x83, 0x98, 0xee, 0x1e, 0xcc, 0x28, 0x2c, 0x3a,
-	0xe9, 0x57, 0xaf, 0xea, 0xbd, 0x97, 0x2a, 0x00, 0x5d, 0xca, 0x7c, 0x54, 0x58, 0x12, 0x52, 0x8d,
-	0x62, 0x12, 0x0f, 0x67, 0x44, 0xb3, 0x27, 0x4c, 0x75, 0x91, 0xa7, 0xda, 0x18, 0x12, 0x2d, 0x39,
-	0x19, 0x0e, 0x1d, 0x31, 0x94, 0x8c, 0x36, 0xfc, 0x93, 0x0e, 0x6c, 0x5f, 0x96, 0x32, 0xbf, 0x16,
-	0x2d, 0x25, 0x67, 0xf8, 0x52, 0x22, 0x4b, 0x72, 0x05, 0x3d, 0x57, 0x74, 0x0f, 0x8d, 0xe4, 0x53,
-	0x2d, 0x58, 0x51, 0x2a, 0x86, 0x96, 0x9b, 0x36, 0xfa, 0x19, 0xfb, 0xd1, 0x41, 0x74, 0xb4, 0x99,
-	0xfd, 0x60, 0xc7, 0x15, 0x9a, 0xf9, 0x95, 0xec, 0x43, 0xbf, 0x11, 0xb8, 0x25, 0x4e, 0xee, 0x40,
-	0xd5, 0x7d, 0xb8, 0x20, 0xc3, 0xa8, 0x8e, 0xe1, 0x9f, 0x9b, 0xf6, 0x4a, 0xed, 0x71, 0x77, 0x54,
-	0x4c, 0x46, 0xb7, 0x8c, 0x76, 0xc9, 0x07, 0xe0, 0x5b, 0x54, 0x0f, 0x36, 0x72, 0xbe, 0xb7, 0x44,
-	0xe2, 0xb5, 0x5b, 0x59, 0x33, 0xe7, 0x8c, 0x48, 0x92, 0x53, 0xe8, 0xaf, 0x86, 0xad, 0xf4, 0x77,
-	0xe0, 0xbf, 0xd0, 0x23, 0x9a, 0x2a, 0x6a, 0x00, 0xe3, 0xcf, 0x08, 0xda, 0x3e, 0x0c, 0xda, 0x45,
-	0x3e, 0x45, 0x75, 0x03, 0xcd, 0x90, 0x4b, 0xf9, 0x04, 0x2b, 0xfb, 0x88, 0x77, 0xff, 0x96, 0x83,
-	0x7c, 0x32, 0x78, 0xfb, 0xf8, 0x7a, 0x6f, 0x74, 0x55, 0xc7, 0x2f, 0x7a, 0x71, 0x96, 0xba, 0x33,
-	0xa4, 0x1c, 0xb4, 0x08, 0xb6, 0xea, 0x99, 0xd4, 0x60, 0x29, 0xb2, 0x66, 0xad, 0xf1, 0x70, 0x3d,
-	0x59, 0xf9, 0x1c, 0x7a, 0x9f, 0xfd, 0x64, 0xef, 0x97, 0x8f, 0xae, 0xb5, 0x5e, 0x44, 0x27, 0x93,
-	0xa6, 0xbf, 0xe8, 0xf9, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x87, 0xd8, 0x13, 0x0a, 0x0d, 0x02,
-	0x00, 0x00,
-}
-
 // Reference imports to suppress errors if they are not otherwise used.
 var _ context.Context
 var _ grpc.ClientConn
@@ -324,3 +295,28 @@ var _AuthService_serviceDesc = grpc.ServiceDesc{
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "auth.proto",
 }
+
+func init() { proto.RegisterFile("auth.proto", fileDescriptor_auth_5d9157b05cb925f8) }
+
+var fileDescriptor_auth_5d9157b05cb925f8 = []byte{
+	// 303 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x51, 0x41, 0x4e, 0xc3, 0x30,
+	0x10, 0x54, 0x22, 0x08, 0x65, 0xcb, 0x05, 0x97, 0xd2, 0x90, 0x56, 0x08, 0x59, 0x1c, 0x80, 0x43,
+	0x02, 0xe5, 0xc6, 0x8d, 0x27, 0x10, 0x40, 0xe2, 0x86, 0x9c, 0x62, 0x15, 0x0b, 0xf0, 0x9a, 0xd8,
+	0x29, 0x77, 0xbe, 0xc0, 0xd3, 0xe0, 0x09, 0x3c, 0x84, 0xd8, 0x4e, 0x50, 0xa0, 0x3d, 0x44, 0xca,
+	0x78, 0x66, 0x67, 0x46, 0xbb, 0x00, 0xac, 0x32, 0x8f, 0xa9, 0x2a, 0xd1, 0x20, 0x09, 0x55, 0x91,
+	0x4c, 0xe6, 0x88, 0xf3, 0x67, 0x9e, 0x31, 0x25, 0x32, 0x26, 0x25, 0x1a, 0x66, 0x04, 0x4a, 0xed,
+	0x15, 0x09, 0x54, 0x9a, 0x97, 0xfe, 0x9f, 0x0e, 0x60, 0xfb, 0xb2, 0x9e, 0xbd, 0xae, 0x15, 0x95,
+	0xce, 0xf9, 0x6b, 0xc5, 0xb5, 0xa1, 0x57, 0x30, 0xb2, 0x8f, 0xf6, 0xe3, 0xd2, 0x88, 0x19, 0x33,
+	0xbc, 0xa1, 0x48, 0x02, 0x3d, 0x3b, 0x2d, 0xd9, 0x0b, 0x8f, 0x83, 0x83, 0xe0, 0x68, 0x33, 0xff,
+	0xc5, 0x96, 0x53, 0x4c, 0xeb, 0x37, 0x2c, 0x1f, 0xe2, 0xd0, 0x73, 0x2d, 0xa6, 0x77, 0x40, 0xba,
+	0x39, 0x5a, 0xd5, 0x75, 0x38, 0x39, 0x86, 0x35, 0x3b, 0xed, 0x9c, 0xfa, 0xd3, 0x61, 0xaa, 0x8a,
+	0xf4, 0xb6, 0xc6, 0x2d, 0xef, 0x81, 0x93, 0x90, 0x11, 0x6c, 0x08, 0x7d, 0x5f, 0x22, 0x1a, 0xe7,
+	0xdd, 0xcb, 0x23, 0xa1, 0xf3, 0x1a, 0xd1, 0x53, 0x88, 0x97, 0xcb, 0x36, 0xfe, 0x3b, 0xb0, 0x6e,
+	0xf0, 0x89, 0xcb, 0xa6, 0xaa, 0x07, 0xd3, 0xaf, 0x00, 0xfa, 0xae, 0x0c, 0x2f, 0x17, 0x62, 0xc6,
+	0xc9, 0x0d, 0x44, 0xbe, 0x17, 0x71, 0x0d, 0x96, 0xf6, 0x91, 0xec, 0xfe, 0x7f, 0xf6, 0xf6, 0x74,
+	0xfc, 0xfe, 0xf9, 0xfd, 0x11, 0x0e, 0xc9, 0xc0, 0x2d, 0x7a, 0x71, 0x96, 0xd9, 0x33, 0x64, 0xda,
+	0x7b, 0x21, 0x6c, 0x75, 0x3b, 0x91, 0x71, 0x6b, 0xb2, 0x62, 0xad, 0xc9, 0x64, 0x35, 0xd9, 0xe4,
+	0x1c, 0xba, 0x9c, 0x7d, 0xba, 0xf7, 0x27, 0x87, 0x75, 0xa4, 0x17, 0xc1, 0x49, 0x11, 0xb9, 0x8b,
+	0x9e, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x87, 0xd8, 0x13, 0x0a, 0x0d, 0x02, 0x00, 0x00,
+}

+ 2 - 2
api/pb/auth.pb.gw.go

@@ -136,9 +136,9 @@ func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 }
 
 var (
-	pattern_AuthService_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "auth", "status"}, ""))
+	pattern_AuthService_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "auth", "status"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_AuthService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "auth", "authenticate"}, ""))
+	pattern_AuthService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "auth", "authenticate"}, "", runtime.AssumeColonVerbOpt(true)))
 )
 
 var (

+ 101 - 116
api/pb/network.pb.go

@@ -3,13 +3,14 @@
 
 package pb
 
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
 import (
-	context "context"
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	_ "google.golang.org/genproto/googleapis/api/annotations"
+	context "golang.org/x/net/context"
 	grpc "google.golang.org/grpc"
-	math "math"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -21,7 +22,7 @@ var _ = math.Inf
 // is compatible with the proto package it is being compiled against.
 // A compilation error at this line likely means your copy of the
 // proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 type NetworkCreateRequest struct {
 	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
@@ -37,17 +38,16 @@ func (m *NetworkCreateRequest) Reset()         { *m = NetworkCreateRequest{} }
 func (m *NetworkCreateRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkCreateRequest) ProtoMessage()    {}
 func (*NetworkCreateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{0}
+	return fileDescriptor_network_34cf09007f6526a1, []int{0}
 }
-
 func (m *NetworkCreateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkCreateRequest.Unmarshal(m, b)
 }
 func (m *NetworkCreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkCreateRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkCreateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkCreateRequest.Merge(m, src)
+func (dst *NetworkCreateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkCreateRequest.Merge(dst, src)
 }
 func (m *NetworkCreateRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkCreateRequest.Size(m)
@@ -96,17 +96,16 @@ func (m *NetworkListRequest) Reset()         { *m = NetworkListRequest{} }
 func (m *NetworkListRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkListRequest) ProtoMessage()    {}
 func (*NetworkListRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{1}
+	return fileDescriptor_network_34cf09007f6526a1, []int{1}
 }
-
 func (m *NetworkListRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkListRequest.Unmarshal(m, b)
 }
 func (m *NetworkListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkListRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkListRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkListRequest.Merge(m, src)
+func (dst *NetworkListRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkListRequest.Merge(dst, src)
 }
 func (m *NetworkListRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkListRequest.Size(m)
@@ -128,17 +127,16 @@ func (m *NetworkDeleteRequest) Reset()         { *m = NetworkDeleteRequest{} }
 func (m *NetworkDeleteRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkDeleteRequest) ProtoMessage()    {}
 func (*NetworkDeleteRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{2}
+	return fileDescriptor_network_34cf09007f6526a1, []int{2}
 }
-
 func (m *NetworkDeleteRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkDeleteRequest.Unmarshal(m, b)
 }
 func (m *NetworkDeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkDeleteRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkDeleteRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkDeleteRequest.Merge(m, src)
+func (dst *NetworkDeleteRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkDeleteRequest.Merge(dst, src)
 }
 func (m *NetworkDeleteRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkDeleteRequest.Size(m)
@@ -166,17 +164,16 @@ func (m *NetworkGetAllTypesRequest) Reset()         { *m = NetworkGetAllTypesReq
 func (m *NetworkGetAllTypesRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkGetAllTypesRequest) ProtoMessage()    {}
 func (*NetworkGetAllTypesRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{3}
+	return fileDescriptor_network_34cf09007f6526a1, []int{3}
 }
-
 func (m *NetworkGetAllTypesRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkGetAllTypesRequest.Unmarshal(m, b)
 }
 func (m *NetworkGetAllTypesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkGetAllTypesRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkGetAllTypesRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkGetAllTypesRequest.Merge(m, src)
+func (dst *NetworkGetAllTypesRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkGetAllTypesRequest.Merge(dst, src)
 }
 func (m *NetworkGetAllTypesRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkGetAllTypesRequest.Size(m)
@@ -199,17 +196,16 @@ func (m *NetworkAssociateRequest) Reset()         { *m = NetworkAssociateRequest
 func (m *NetworkAssociateRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkAssociateRequest) ProtoMessage()    {}
 func (*NetworkAssociateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{4}
+	return fileDescriptor_network_34cf09007f6526a1, []int{4}
 }
-
 func (m *NetworkAssociateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkAssociateRequest.Unmarshal(m, b)
 }
 func (m *NetworkAssociateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkAssociateRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkAssociateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkAssociateRequest.Merge(m, src)
+func (dst *NetworkAssociateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkAssociateRequest.Merge(dst, src)
 }
 func (m *NetworkAssociateRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkAssociateRequest.Size(m)
@@ -246,17 +242,16 @@ func (m *NetworkDissociateRequest) Reset()         { *m = NetworkDissociateReque
 func (m *NetworkDissociateRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkDissociateRequest) ProtoMessage()    {}
 func (*NetworkDissociateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{5}
+	return fileDescriptor_network_34cf09007f6526a1, []int{5}
 }
-
 func (m *NetworkDissociateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkDissociateRequest.Unmarshal(m, b)
 }
 func (m *NetworkDissociateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkDissociateRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkDissociateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkDissociateRequest.Merge(m, src)
+func (dst *NetworkDissociateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkDissociateRequest.Merge(dst, src)
 }
 func (m *NetworkDissociateRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkDissociateRequest.Size(m)
@@ -292,17 +287,16 @@ func (m *NetworkGetAssociatedUsersRequest) Reset()         { *m = NetworkGetAsso
 func (m *NetworkGetAssociatedUsersRequest) String() string { return proto.CompactTextString(m) }
 func (*NetworkGetAssociatedUsersRequest) ProtoMessage()    {}
 func (*NetworkGetAssociatedUsersRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{6}
+	return fileDescriptor_network_34cf09007f6526a1, []int{6}
 }
-
 func (m *NetworkGetAssociatedUsersRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkGetAssociatedUsersRequest.Unmarshal(m, b)
 }
 func (m *NetworkGetAssociatedUsersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkGetAssociatedUsersRequest.Marshal(b, m, deterministic)
 }
-func (m *NetworkGetAssociatedUsersRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkGetAssociatedUsersRequest.Merge(m, src)
+func (dst *NetworkGetAssociatedUsersRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkGetAssociatedUsersRequest.Merge(dst, src)
 }
 func (m *NetworkGetAssociatedUsersRequest) XXX_Size() int {
 	return xxx_messageInfo_NetworkGetAssociatedUsersRequest.Size(m)
@@ -336,17 +330,16 @@ func (m *Network) Reset()         { *m = Network{} }
 func (m *Network) String() string { return proto.CompactTextString(m) }
 func (*Network) ProtoMessage()    {}
 func (*Network) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{7}
+	return fileDescriptor_network_34cf09007f6526a1, []int{7}
 }
-
 func (m *Network) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_Network.Unmarshal(m, b)
 }
 func (m *Network) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_Network.Marshal(b, m, deterministic)
 }
-func (m *Network) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Network.Merge(m, src)
+func (dst *Network) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Network.Merge(dst, src)
 }
 func (m *Network) XXX_Size() int {
 	return xxx_messageInfo_Network.Size(m)
@@ -411,17 +404,16 @@ func (m *NetworkType) Reset()         { *m = NetworkType{} }
 func (m *NetworkType) String() string { return proto.CompactTextString(m) }
 func (*NetworkType) ProtoMessage()    {}
 func (*NetworkType) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{8}
+	return fileDescriptor_network_34cf09007f6526a1, []int{8}
 }
-
 func (m *NetworkType) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkType.Unmarshal(m, b)
 }
 func (m *NetworkType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkType.Marshal(b, m, deterministic)
 }
-func (m *NetworkType) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkType.Merge(m, src)
+func (dst *NetworkType) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkType.Merge(dst, src)
 }
 func (m *NetworkType) XXX_Size() int {
 	return xxx_messageInfo_NetworkType.Size(m)
@@ -457,17 +449,16 @@ func (m *NetworkCreateResponse) Reset()         { *m = NetworkCreateResponse{} }
 func (m *NetworkCreateResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkCreateResponse) ProtoMessage()    {}
 func (*NetworkCreateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{9}
+	return fileDescriptor_network_34cf09007f6526a1, []int{9}
 }
-
 func (m *NetworkCreateResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkCreateResponse.Unmarshal(m, b)
 }
 func (m *NetworkCreateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkCreateResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkCreateResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkCreateResponse.Merge(m, src)
+func (dst *NetworkCreateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkCreateResponse.Merge(dst, src)
 }
 func (m *NetworkCreateResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkCreateResponse.Size(m)
@@ -496,17 +487,16 @@ func (m *NetworkListResponse) Reset()         { *m = NetworkListResponse{} }
 func (m *NetworkListResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkListResponse) ProtoMessage()    {}
 func (*NetworkListResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{10}
+	return fileDescriptor_network_34cf09007f6526a1, []int{10}
 }
-
 func (m *NetworkListResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkListResponse.Unmarshal(m, b)
 }
 func (m *NetworkListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkListResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkListResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkListResponse.Merge(m, src)
+func (dst *NetworkListResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkListResponse.Merge(dst, src)
 }
 func (m *NetworkListResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkListResponse.Size(m)
@@ -535,17 +525,16 @@ func (m *NetworkDeleteResponse) Reset()         { *m = NetworkDeleteResponse{} }
 func (m *NetworkDeleteResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkDeleteResponse) ProtoMessage()    {}
 func (*NetworkDeleteResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{11}
+	return fileDescriptor_network_34cf09007f6526a1, []int{11}
 }
-
 func (m *NetworkDeleteResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkDeleteResponse.Unmarshal(m, b)
 }
 func (m *NetworkDeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkDeleteResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkDeleteResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkDeleteResponse.Merge(m, src)
+func (dst *NetworkDeleteResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkDeleteResponse.Merge(dst, src)
 }
 func (m *NetworkDeleteResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkDeleteResponse.Size(m)
@@ -574,17 +563,16 @@ func (m *NetworkGetAllTypesResponse) Reset()         { *m = NetworkGetAllTypesRe
 func (m *NetworkGetAllTypesResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkGetAllTypesResponse) ProtoMessage()    {}
 func (*NetworkGetAllTypesResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{12}
+	return fileDescriptor_network_34cf09007f6526a1, []int{12}
 }
-
 func (m *NetworkGetAllTypesResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkGetAllTypesResponse.Unmarshal(m, b)
 }
 func (m *NetworkGetAllTypesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkGetAllTypesResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkGetAllTypesResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkGetAllTypesResponse.Merge(m, src)
+func (dst *NetworkGetAllTypesResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkGetAllTypesResponse.Merge(dst, src)
 }
 func (m *NetworkGetAllTypesResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkGetAllTypesResponse.Size(m)
@@ -612,17 +600,16 @@ func (m *NetworkAssociateResponse) Reset()         { *m = NetworkAssociateRespon
 func (m *NetworkAssociateResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkAssociateResponse) ProtoMessage()    {}
 func (*NetworkAssociateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{13}
+	return fileDescriptor_network_34cf09007f6526a1, []int{13}
 }
-
 func (m *NetworkAssociateResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkAssociateResponse.Unmarshal(m, b)
 }
 func (m *NetworkAssociateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkAssociateResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkAssociateResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkAssociateResponse.Merge(m, src)
+func (dst *NetworkAssociateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkAssociateResponse.Merge(dst, src)
 }
 func (m *NetworkAssociateResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkAssociateResponse.Size(m)
@@ -643,17 +630,16 @@ func (m *NetworkDissociateResponse) Reset()         { *m = NetworkDissociateResp
 func (m *NetworkDissociateResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkDissociateResponse) ProtoMessage()    {}
 func (*NetworkDissociateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{14}
+	return fileDescriptor_network_34cf09007f6526a1, []int{14}
 }
-
 func (m *NetworkDissociateResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkDissociateResponse.Unmarshal(m, b)
 }
 func (m *NetworkDissociateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkDissociateResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkDissociateResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkDissociateResponse.Merge(m, src)
+func (dst *NetworkDissociateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkDissociateResponse.Merge(dst, src)
 }
 func (m *NetworkDissociateResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkDissociateResponse.Size(m)
@@ -675,17 +661,16 @@ func (m *NetworkGetAssociatedUsersResponse) Reset()         { *m = NetworkGetAss
 func (m *NetworkGetAssociatedUsersResponse) String() string { return proto.CompactTextString(m) }
 func (*NetworkGetAssociatedUsersResponse) ProtoMessage()    {}
 func (*NetworkGetAssociatedUsersResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_8571034d60397816, []int{15}
+	return fileDescriptor_network_34cf09007f6526a1, []int{15}
 }
-
 func (m *NetworkGetAssociatedUsersResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_NetworkGetAssociatedUsersResponse.Unmarshal(m, b)
 }
 func (m *NetworkGetAssociatedUsersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_NetworkGetAssociatedUsersResponse.Marshal(b, m, deterministic)
 }
-func (m *NetworkGetAssociatedUsersResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NetworkGetAssociatedUsersResponse.Merge(m, src)
+func (dst *NetworkGetAssociatedUsersResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetworkGetAssociatedUsersResponse.Merge(dst, src)
 }
 func (m *NetworkGetAssociatedUsersResponse) XXX_Size() int {
 	return xxx_messageInfo_NetworkGetAssociatedUsersResponse.Size(m)
@@ -722,52 +707,6 @@ func init() {
 	proto.RegisterType((*NetworkGetAssociatedUsersResponse)(nil), "pb.NetworkGetAssociatedUsersResponse")
 }
 
-func init() { proto.RegisterFile("network.proto", fileDescriptor_8571034d60397816) }
-
-var fileDescriptor_8571034d60397816 = []byte{
-	// 640 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4d, 0x6f, 0xda, 0x40,
-	0x10, 0x95, 0x81, 0x90, 0x30, 0xa8, 0x1f, 0xda, 0x50, 0x62, 0x0c, 0xa4, 0x64, 0x0b, 0x6a, 0xc4,
-	0x01, 0x94, 0x54, 0xea, 0xa1, 0x87, 0x48, 0x88, 0x4a, 0x55, 0xab, 0xaa, 0x07, 0xda, 0x9c, 0x13,
-	0x83, 0x57, 0xc8, 0xaa, 0x6b, 0x3b, 0xde, 0x85, 0x2a, 0xd7, 0xde, 0xdb, 0x4b, 0x7f, 0x45, 0x7f,
-	0x4f, 0xff, 0x42, 0x7f, 0x48, 0xb5, 0xeb, 0xb1, 0x59, 0x9b, 0x8f, 0x28, 0xca, 0x6d, 0x99, 0x99,
-	0x7d, 0xef, 0x79, 0xdf, 0xd3, 0x00, 0x8f, 0x7c, 0x26, 0xbe, 0x07, 0xd1, 0xd7, 0x41, 0x18, 0x05,
-	0x22, 0x20, 0x85, 0x70, 0x6a, 0xb5, 0xe6, 0x41, 0x30, 0xf7, 0xd8, 0xd0, 0x0e, 0xdd, 0xa1, 0xed,
-	0xfb, 0x81, 0xb0, 0x85, 0x1b, 0xf8, 0x3c, 0x9e, 0xa0, 0x0e, 0xd4, 0x3e, 0xc5, 0x57, 0xc6, 0x11,
-	0xb3, 0x05, 0x9b, 0xb0, 0x9b, 0x05, 0xe3, 0x82, 0x10, 0x28, 0xf9, 0xf6, 0x37, 0x66, 0x1a, 0x1d,
-	0xe3, 0xb4, 0x32, 0x51, 0x67, 0x59, 0x9b, 0xb9, 0x4e, 0x64, 0x16, 0xe2, 0x9a, 0x3c, 0xcb, 0x9a,
-	0xb8, 0x0d, 0x99, 0x59, 0x8c, 0x6b, 0xf2, 0x4c, 0x9e, 0x42, 0x71, 0xe9, 0xda, 0x66, 0x49, 0x95,
-	0xe4, 0x91, 0xd6, 0x80, 0x20, 0xcb, 0x47, 0x97, 0x0b, 0xe4, 0xa0, 0xfd, 0x94, 0xfb, 0x2d, 0xf3,
-	0xd8, 0x4e, 0x6e, 0xda, 0x84, 0x06, 0xce, 0xbe, 0x63, 0x62, 0xe4, 0x79, 0x5f, 0x6e, 0x43, 0xc6,
-	0x13, 0xa0, 0xf7, 0x70, 0x84, 0xcd, 0x11, 0xe7, 0xc1, 0xcc, 0xbd, 0xe3, 0x3b, 0x2c, 0x38, 0x58,
-	0x70, 0x16, 0xa9, 0x7a, 0xfc, 0x2d, 0xe9, 0x6f, 0xfa, 0x01, 0xcc, 0x44, 0x93, 0xfb, 0x50, 0xac,
-	0xd7, 0xd0, 0xd1, 0x34, 0x27, 0x68, 0xce, 0x25, 0x67, 0x11, 0xdf, 0xf5, 0xad, 0x7f, 0x0c, 0xd8,
-	0xc7, 0x8b, 0x0f, 0xf2, 0xa1, 0x0d, 0x30, 0x53, 0xa6, 0x3a, 0x57, 0xb6, 0x40, 0x3b, 0x2a, 0x58,
-	0x19, 0x09, 0x72, 0x06, 0x35, 0x3b, 0x15, 0x75, 0x95, 0xa8, 0xe6, 0xe6, 0x5e, 0xa7, 0x78, 0x5a,
-	0x99, 0x1c, 0xda, 0x19, 0xc1, 0xaa, 0x95, 0x38, 0x5b, 0x5e, 0x39, 0x3b, 0x86, 0x2a, 0x4a, 0x95,
-	0x8e, 0xa4, 0x32, 0x0c, 0x4d, 0x46, 0x07, 0xaa, 0x0e, 0xe3, 0xb3, 0xc8, 0x0d, 0x65, 0xf0, 0x50,
-	0xb5, 0x5e, 0xa2, 0x17, 0xf0, 0x2c, 0x17, 0x42, 0x1e, 0x06, 0x3e, 0x67, 0xa4, 0x07, 0xfb, 0x18,
-	0x68, 0x85, 0x58, 0x3d, 0xaf, 0x0e, 0xc2, 0xe9, 0x00, 0x67, 0x27, 0x49, 0x8f, 0x5e, 0xc0, 0x61,
-	0x26, 0x5e, 0x78, 0xfb, 0x25, 0x1c, 0xe0, 0x04, 0x37, 0x8d, 0x4e, 0x31, 0x7f, 0x3d, 0x6d, 0x6a,
-	0xfc, 0x49, 0x10, 0xef, 0xc7, 0x3f, 0x06, 0x6b, 0x53, 0x38, 0x53, 0x90, 0x3d, 0xf9, 0x0e, 0x89,
-	0x86, 0x27, 0x1a, 0x84, 0x1c, 0x9c, 0xc4, 0x5d, 0x6a, 0xa5, 0xc9, 0xd3, 0x42, 0x1c, 0x43, 0x68,
-	0xe9, 0xd7, 0x53, 0x89, 0xcd, 0x11, 0x9c, 0xec, 0x88, 0x19, 0x8a, 0x68, 0x41, 0x65, 0xe5, 0xb0,
-	0xa1, 0x1c, 0x5e, 0x15, 0xce, 0x7f, 0x95, 0xe1, 0x31, 0x62, 0x7c, 0x66, 0xd1, 0xd2, 0x9d, 0x31,
-	0x72, 0x0d, 0xe5, 0xd8, 0x0c, 0x62, 0x6a, 0x82, 0x33, 0x4b, 0xc2, 0x6a, 0x6c, 0xe8, 0xa0, 0xa8,
-	0x93, 0x1f, 0x7f, 0xff, 0xfd, 0x2e, 0x34, 0x69, 0x5d, 0xed, 0x9d, 0xe5, 0xd9, 0x10, 0xdf, 0x6a,
-	0x18, 0xe7, 0xef, 0x8d, 0xd1, 0x27, 0x97, 0x50, 0x92, 0x76, 0x91, 0xba, 0x86, 0xa2, 0xad, 0x07,
-	0xeb, 0x68, 0xad, 0x8e, 0xd8, 0x2d, 0x85, 0x5d, 0x27, 0xb5, 0x3c, 0xb6, 0x27, 0xe1, 0xae, 0xa1,
-	0x1c, 0xbb, 0x98, 0x11, 0x9e, 0xd9, 0x30, 0x19, 0xe1, 0x59, 0xcb, 0xb7, 0x0b, 0x77, 0xd4, 0x9c,
-	0x14, 0x7e, 0x03, 0x55, 0xcd, 0x67, 0xd2, 0xd6, 0xc0, 0xd6, 0x97, 0x93, 0x75, 0xbc, 0xad, 0x8d,
-	0x84, 0x2f, 0x14, 0x61, 0x9b, 0x34, 0xf3, 0x84, 0x73, 0x26, 0x6c, 0xcf, 0x53, 0xe1, 0x20, 0x3f,
-	0x0d, 0x20, 0xeb, 0xee, 0x92, 0x6e, 0x0e, 0x7b, 0xe3, 0x8e, 0xb1, 0x7a, 0x77, 0x4c, 0xa1, 0x90,
-	0xbe, 0x12, 0xd2, 0x25, 0x74, 0x93, 0x90, 0xf4, 0xce, 0x42, 0x11, 0x7b, 0x50, 0x49, 0x61, 0x48,
-	0x53, 0xc3, 0xcf, 0x2f, 0x60, 0xab, 0xb5, 0xb9, 0x89, 0x9c, 0x5d, 0xc5, 0x79, 0x4c, 0x1b, 0x79,
-	0xce, 0x94, 0x50, 0x3e, 0x78, 0x08, 0xb0, 0xca, 0x3d, 0xd1, 0x11, 0xd7, 0x96, 0xb4, 0xd5, 0xde,
-	0xd2, 0x45, 0xc2, 0x9e, 0x22, 0x7c, 0x4e, 0xad, 0x35, 0x7b, 0x5d, 0x8d, 0x71, 0x5a, 0x56, 0xff,
-	0x8e, 0xaf, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0xab, 0x14, 0xfe, 0x39, 0x50, 0x07, 0x00, 0x00,
-}
-
 // Reference imports to suppress errors if they are not otherwise used.
 var _ context.Context
 var _ grpc.ClientConn
@@ -1037,3 +976,49 @@ var _NetworkService_serviceDesc = grpc.ServiceDesc{
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "network.proto",
 }
+
+func init() { proto.RegisterFile("network.proto", fileDescriptor_network_34cf09007f6526a1) }
+
+var fileDescriptor_network_34cf09007f6526a1 = []byte{
+	// 637 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x55, 0xcd, 0x8e, 0xd2, 0x50,
+	0x18, 0x4d, 0x81, 0x61, 0x86, 0x8f, 0xf8, 0x93, 0x3b, 0xc8, 0x94, 0x02, 0x23, 0x73, 0x85, 0x68,
+	0x58, 0x40, 0x66, 0x4c, 0x5c, 0xb8, 0x30, 0x21, 0x98, 0x18, 0x8d, 0x71, 0x81, 0xce, 0x7a, 0x2c,
+	0xf4, 0x86, 0x34, 0x56, 0xda, 0xe9, 0xbd, 0x60, 0xdc, 0xba, 0xd7, 0x8d, 0x4f, 0xe1, 0xf3, 0xf8,
+	0x0a, 0x3e, 0x88, 0xbd, 0xb7, 0x5f, 0xcb, 0x6d, 0xf9, 0x99, 0x4c, 0x66, 0x57, 0xbe, 0x9f, 0x73,
+	0x4e, 0x7b, 0x4e, 0x3e, 0xe0, 0xde, 0x82, 0x89, 0x6f, 0x7e, 0xf8, 0x65, 0x10, 0x84, 0xbe, 0xf0,
+	0x49, 0x21, 0x98, 0x5a, 0xad, 0xb9, 0xef, 0xcf, 0x3d, 0x36, 0xb4, 0x03, 0x77, 0x68, 0x2f, 0x16,
+	0xbe, 0xb0, 0x85, 0xeb, 0x2f, 0x78, 0x3c, 0x41, 0x1d, 0xa8, 0x7d, 0x88, 0x57, 0xc6, 0x21, 0xb3,
+	0x05, 0x9b, 0xb0, 0xeb, 0x25, 0xe3, 0x82, 0x10, 0x28, 0x2d, 0xec, 0xaf, 0xcc, 0x34, 0x3a, 0xc6,
+	0xb3, 0xca, 0x44, 0x3d, 0xcb, 0xda, 0xcc, 0x75, 0x42, 0xb3, 0x10, 0xd7, 0xe4, 0xb3, 0xac, 0x89,
+	0xef, 0x01, 0x33, 0x8b, 0x71, 0x4d, 0x3e, 0x93, 0x87, 0x50, 0x5c, 0xb9, 0xb6, 0x59, 0x52, 0x25,
+	0xf9, 0x48, 0x6b, 0x40, 0x90, 0xe5, 0xbd, 0xcb, 0x05, 0x72, 0xd0, 0x7e, 0xca, 0xfd, 0x9a, 0x79,
+	0x6c, 0x2f, 0x37, 0x6d, 0x42, 0x03, 0x67, 0xdf, 0x30, 0x31, 0xf2, 0xbc, 0x4f, 0x11, 0x11, 0x4f,
+	0x80, 0xde, 0xc2, 0x09, 0x36, 0x47, 0x9c, 0xfb, 0x33, 0xf7, 0x86, 0xf7, 0xb0, 0xe0, 0x68, 0xc9,
+	0x59, 0xa8, 0xea, 0xf1, 0xbb, 0xa4, 0xbf, 0xe9, 0x3b, 0x30, 0x13, 0x4d, 0xee, 0x5d, 0xb1, 0x5e,
+	0x40, 0x47, 0xd3, 0x9c, 0xa0, 0x39, 0x97, 0x51, 0x9f, 0xef, 0x7b, 0xd7, 0x3f, 0x06, 0x1c, 0xe2,
+	0xe2, 0x9d, 0x7c, 0x68, 0x03, 0xcc, 0x94, 0xa9, 0xce, 0x95, 0x2d, 0xd0, 0x8e, 0x0a, 0x56, 0x46,
+	0x82, 0x9c, 0x43, 0xcd, 0x4e, 0x45, 0x5d, 0x25, 0xaa, 0xb9, 0x79, 0xd0, 0x29, 0x46, 0x83, 0xc7,
+	0x76, 0x46, 0xb0, 0x6a, 0x25, 0xce, 0x96, 0xd7, 0xce, 0x8e, 0xa1, 0x8a, 0x52, 0xa5, 0x23, 0xa9,
+	0x0c, 0x43, 0x93, 0xd1, 0x81, 0xaa, 0xc3, 0xf8, 0x2c, 0x74, 0x03, 0x19, 0x3c, 0x54, 0xad, 0x97,
+	0xe8, 0x2b, 0x78, 0x94, 0x0b, 0x21, 0x0f, 0xa2, 0x88, 0x32, 0xd2, 0x83, 0x43, 0x0c, 0xb4, 0x42,
+	0xac, 0x5e, 0x54, 0x07, 0xc1, 0x74, 0x80, 0xb3, 0x93, 0xa4, 0x17, 0xed, 0x1f, 0x67, 0xe2, 0x85,
+	0xdb, 0x4f, 0xe1, 0x08, 0x27, 0x78, 0xb4, 0x5e, 0xcc, 0xaf, 0xa7, 0x4d, 0x8d, 0x3f, 0x09, 0xe2,
+	0xed, 0xf8, 0xc7, 0x60, 0x6d, 0x0b, 0x67, 0x0a, 0x72, 0x20, 0xbf, 0x43, 0xa2, 0xe1, 0x81, 0x06,
+	0x21, 0x07, 0x27, 0x71, 0x97, 0x5a, 0x69, 0xf2, 0xb4, 0x10, 0xc7, 0x10, 0x5a, 0xfa, 0xf5, 0x54,
+	0x62, 0x73, 0x04, 0x67, 0x7b, 0x62, 0x86, 0x22, 0x5a, 0x50, 0x59, 0x3b, 0x6c, 0x28, 0x87, 0xd7,
+	0x85, 0x8b, 0x5f, 0x65, 0xb8, 0x8f, 0x18, 0x1f, 0x59, 0xb8, 0x72, 0x67, 0x8c, 0x7c, 0x86, 0x72,
+	0x6c, 0x06, 0x31, 0x35, 0xc1, 0x99, 0x23, 0x61, 0x35, 0xb6, 0x74, 0x50, 0xd4, 0xd9, 0x8f, 0xbf,
+	0xff, 0x7e, 0x17, 0x9a, 0xb4, 0xae, 0xee, 0xce, 0xea, 0x7c, 0x88, 0xdf, 0x6a, 0x18, 0xe7, 0xef,
+	0xa5, 0xd1, 0x27, 0x97, 0x50, 0x92, 0x76, 0x91, 0xba, 0x86, 0xa2, 0x9d, 0x07, 0xeb, 0x64, 0xa3,
+	0x8e, 0xd8, 0x2d, 0x85, 0x5d, 0x27, 0xb5, 0x3c, 0xb6, 0x27, 0xe1, 0x22, 0xe1, 0xb1, 0x8b, 0x19,
+	0xe1, 0x99, 0x0b, 0x93, 0x11, 0x9e, 0xb5, 0x7c, 0xb7, 0x70, 0x47, 0xcd, 0x49, 0xe1, 0xd7, 0x50,
+	0xd5, 0x7c, 0x26, 0x6d, 0x0d, 0x6c, 0xf3, 0x38, 0x59, 0xa7, 0xbb, 0xda, 0x48, 0xf8, 0x44, 0x11,
+	0xb6, 0x49, 0x33, 0x4f, 0x38, 0x67, 0xc2, 0xf6, 0x3c, 0x15, 0x0e, 0xf2, 0xd3, 0x00, 0xb2, 0xe9,
+	0x2e, 0xe9, 0xe6, 0xb0, 0xb7, 0xde, 0x18, 0xab, 0x77, 0xc3, 0x14, 0x0a, 0xe9, 0x2b, 0x21, 0x5d,
+	0x42, 0xb7, 0x09, 0x49, 0x77, 0x96, 0x8a, 0xd8, 0x83, 0x4a, 0x0a, 0x43, 0x9a, 0x1a, 0x7e, 0xfe,
+	0x00, 0x5b, 0xad, 0xed, 0x4d, 0xe4, 0xec, 0x2a, 0xce, 0x53, 0xda, 0xc8, 0x73, 0xa6, 0x84, 0xf2,
+	0x83, 0x07, 0x00, 0xeb, 0xdc, 0x13, 0x1d, 0x71, 0xe3, 0x48, 0x5b, 0xed, 0x1d, 0x5d, 0x24, 0xec,
+	0x29, 0xc2, 0xc7, 0xd4, 0xda, 0xb0, 0xd7, 0xd5, 0x18, 0xa7, 0x65, 0xf5, 0xef, 0xf8, 0xfc, 0x7f,
+	0x00, 0x00, 0x00, 0xff, 0xff, 0xab, 0x14, 0xfe, 0x39, 0x50, 0x07, 0x00, 0x00,
+}

+ 11 - 8
api/pb/network.pb.gw.go

@@ -88,7 +88,10 @@ func request_NetworkService_GetAssociatedUsers_0(ctx context.Context, marshaler
 	var protoReq NetworkGetAssociatedUsersRequest
 	var metadata runtime.ServerMetadata
 
-	if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_NetworkService_GetAssociatedUsers_0); err != nil {
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkService_GetAssociatedUsers_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -313,19 +316,19 @@ func RegisterNetworkServiceHandlerClient(ctx context.Context, mux *runtime.Serve
 }
 
 var (
-	pattern_NetworkService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "create"}, ""))
+	pattern_NetworkService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "create"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "list"}, ""))
+	pattern_NetworkService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "list"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "delete"}, ""))
+	pattern_NetworkService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "delete"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_GetAllTypes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "getalltypes"}, ""))
+	pattern_NetworkService_GetAllTypes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "getalltypes"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_GetAssociatedUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "getassociatedusers"}, ""))
+	pattern_NetworkService_GetAssociatedUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "getassociatedusers"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_Associate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "associate"}, ""))
+	pattern_NetworkService_Associate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "associate"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_NetworkService_Dissociate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "dissociate"}, ""))
+	pattern_NetworkService_Dissociate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "network", "dissociate"}, "", runtime.AssumeColonVerbOpt(true)))
 )
 
 var (

+ 123 - 112
api/pb/user.pb.go

@@ -3,13 +3,14 @@
 
 package pb
 
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
 import (
-	context "context"
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	_ "google.golang.org/genproto/googleapis/api/annotations"
+	context "golang.org/x/net/context"
 	grpc "google.golang.org/grpc"
-	math "math"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -21,7 +22,7 @@ var _ = math.Inf
 // is compatible with the proto package it is being compiled against.
 // A compilation error at this line likely means your copy of the
 // proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 type UserUpdateRequest_GWPref int32
 
@@ -36,7 +37,6 @@ var UserUpdateRequest_GWPref_name = map[int32]string{
 	1: "NOGW",
 	2: "GW",
 }
-
 var UserUpdateRequest_GWPref_value = map[string]int32{
 	"NOPREF": 0,
 	"NOGW":   1,
@@ -46,9 +46,8 @@ var UserUpdateRequest_GWPref_value = map[string]int32{
 func (x UserUpdateRequest_GWPref) String() string {
 	return proto.EnumName(UserUpdateRequest_GWPref_name, int32(x))
 }
-
 func (UserUpdateRequest_GWPref) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{2, 0}
+	return fileDescriptor_user_32c669a016e64e35, []int{2, 0}
 }
 
 type UserUpdateRequest_StaticPref int32
@@ -64,7 +63,6 @@ var UserUpdateRequest_StaticPref_name = map[int32]string{
 	1: "NOSTATIC",
 	2: "STATIC",
 }
-
 var UserUpdateRequest_StaticPref_value = map[string]int32{
 	"NOPREFSTATIC": 0,
 	"NOSTATIC":     1,
@@ -74,9 +72,8 @@ var UserUpdateRequest_StaticPref_value = map[string]int32{
 func (x UserUpdateRequest_StaticPref) String() string {
 	return proto.EnumName(UserUpdateRequest_StaticPref_name, int32(x))
 }
-
 func (UserUpdateRequest_StaticPref) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{2, 1}
+	return fileDescriptor_user_32c669a016e64e35, []int{2, 1}
 }
 
 type UserUpdateRequest_AdminPref int32
@@ -92,7 +89,6 @@ var UserUpdateRequest_AdminPref_name = map[int32]string{
 	1: "NOADMIN",
 	2: "ADMIN",
 }
-
 var UserUpdateRequest_AdminPref_value = map[string]int32{
 	"NOPREFADMIN": 0,
 	"NOADMIN":     1,
@@ -102,9 +98,8 @@ var UserUpdateRequest_AdminPref_value = map[string]int32{
 func (x UserUpdateRequest_AdminPref) String() string {
 	return proto.EnumName(UserUpdateRequest_AdminPref_name, int32(x))
 }
-
 func (UserUpdateRequest_AdminPref) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{2, 2}
+	return fileDescriptor_user_32c669a016e64e35, []int{2, 2}
 }
 
 type UserListRequest struct {
@@ -117,17 +112,16 @@ func (m *UserListRequest) Reset()         { *m = UserListRequest{} }
 func (m *UserListRequest) String() string { return proto.CompactTextString(m) }
 func (*UserListRequest) ProtoMessage()    {}
 func (*UserListRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{0}
+	return fileDescriptor_user_32c669a016e64e35, []int{0}
 }
-
 func (m *UserListRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserListRequest.Unmarshal(m, b)
 }
 func (m *UserListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserListRequest.Marshal(b, m, deterministic)
 }
-func (m *UserListRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserListRequest.Merge(m, src)
+func (dst *UserListRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserListRequest.Merge(dst, src)
 }
 func (m *UserListRequest) XXX_Size() int {
 	return xxx_messageInfo_UserListRequest.Size(m)
@@ -144,6 +138,7 @@ type UserCreateRequest struct {
 	NoGw                 bool     `protobuf:"varint,3,opt,name=no_gw,json=noGw,proto3" json:"no_gw,omitempty"`
 	HostId               uint32   `protobuf:"varint,4,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"`
 	IsAdmin              bool     `protobuf:"varint,5,opt,name=is_admin,json=isAdmin,proto3" json:"is_admin,omitempty"`
+	Description          string   `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -153,17 +148,16 @@ func (m *UserCreateRequest) Reset()         { *m = UserCreateRequest{} }
 func (m *UserCreateRequest) String() string { return proto.CompactTextString(m) }
 func (*UserCreateRequest) ProtoMessage()    {}
 func (*UserCreateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{1}
+	return fileDescriptor_user_32c669a016e64e35, []int{1}
 }
-
 func (m *UserCreateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserCreateRequest.Unmarshal(m, b)
 }
 func (m *UserCreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserCreateRequest.Marshal(b, m, deterministic)
 }
-func (m *UserCreateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserCreateRequest.Merge(m, src)
+func (dst *UserCreateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserCreateRequest.Merge(dst, src)
 }
 func (m *UserCreateRequest) XXX_Size() int {
 	return xxx_messageInfo_UserCreateRequest.Size(m)
@@ -209,6 +203,13 @@ func (m *UserCreateRequest) GetIsAdmin() bool {
 	return false
 }
 
+func (m *UserCreateRequest) GetDescription() string {
+	if m != nil {
+		return m.Description
+	}
+	return ""
+}
+
 type UserUpdateRequest struct {
 	Username             string                       `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
 	Password             string                       `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
@@ -216,6 +217,7 @@ type UserUpdateRequest struct {
 	HostId               uint32                       `protobuf:"varint,4,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"`
 	StaticPref           UserUpdateRequest_StaticPref `protobuf:"varint,5,opt,name=static_pref,json=staticPref,proto3,enum=pb.UserUpdateRequest_StaticPref" json:"static_pref,omitempty"`
 	AdminPref            UserUpdateRequest_AdminPref  `protobuf:"varint,6,opt,name=admin_pref,json=adminPref,proto3,enum=pb.UserUpdateRequest_AdminPref" json:"admin_pref,omitempty"`
+	Description          string                       `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}                     `json:"-"`
 	XXX_unrecognized     []byte                       `json:"-"`
 	XXX_sizecache        int32                        `json:"-"`
@@ -225,17 +227,16 @@ func (m *UserUpdateRequest) Reset()         { *m = UserUpdateRequest{} }
 func (m *UserUpdateRequest) String() string { return proto.CompactTextString(m) }
 func (*UserUpdateRequest) ProtoMessage()    {}
 func (*UserUpdateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{2}
+	return fileDescriptor_user_32c669a016e64e35, []int{2}
 }
-
 func (m *UserUpdateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserUpdateRequest.Unmarshal(m, b)
 }
 func (m *UserUpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserUpdateRequest.Marshal(b, m, deterministic)
 }
-func (m *UserUpdateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserUpdateRequest.Merge(m, src)
+func (dst *UserUpdateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserUpdateRequest.Merge(dst, src)
 }
 func (m *UserUpdateRequest) XXX_Size() int {
 	return xxx_messageInfo_UserUpdateRequest.Size(m)
@@ -288,6 +289,13 @@ func (m *UserUpdateRequest) GetAdminPref() UserUpdateRequest_AdminPref {
 	return UserUpdateRequest_NOPREFADMIN
 }
 
+func (m *UserUpdateRequest) GetDescription() string {
+	if m != nil {
+		return m.Description
+	}
+	return ""
+}
+
 type UserDeleteRequest struct {
 	Username             string   `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -299,17 +307,16 @@ func (m *UserDeleteRequest) Reset()         { *m = UserDeleteRequest{} }
 func (m *UserDeleteRequest) String() string { return proto.CompactTextString(m) }
 func (*UserDeleteRequest) ProtoMessage()    {}
 func (*UserDeleteRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{3}
+	return fileDescriptor_user_32c669a016e64e35, []int{3}
 }
-
 func (m *UserDeleteRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserDeleteRequest.Unmarshal(m, b)
 }
 func (m *UserDeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserDeleteRequest.Marshal(b, m, deterministic)
 }
-func (m *UserDeleteRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserDeleteRequest.Merge(m, src)
+func (dst *UserDeleteRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserDeleteRequest.Merge(dst, src)
 }
 func (m *UserDeleteRequest) XXX_Size() int {
 	return xxx_messageInfo_UserDeleteRequest.Size(m)
@@ -338,17 +345,16 @@ func (m *UserRenewRequest) Reset()         { *m = UserRenewRequest{} }
 func (m *UserRenewRequest) String() string { return proto.CompactTextString(m) }
 func (*UserRenewRequest) ProtoMessage()    {}
 func (*UserRenewRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{4}
+	return fileDescriptor_user_32c669a016e64e35, []int{4}
 }
-
 func (m *UserRenewRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserRenewRequest.Unmarshal(m, b)
 }
 func (m *UserRenewRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserRenewRequest.Marshal(b, m, deterministic)
 }
-func (m *UserRenewRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserRenewRequest.Merge(m, src)
+func (dst *UserRenewRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserRenewRequest.Merge(dst, src)
 }
 func (m *UserRenewRequest) XXX_Size() int {
 	return xxx_messageInfo_UserRenewRequest.Size(m)
@@ -377,17 +383,16 @@ func (m *UserGenConfigRequest) Reset()         { *m = UserGenConfigRequest{} }
 func (m *UserGenConfigRequest) String() string { return proto.CompactTextString(m) }
 func (*UserGenConfigRequest) ProtoMessage()    {}
 func (*UserGenConfigRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{5}
+	return fileDescriptor_user_32c669a016e64e35, []int{5}
 }
-
 func (m *UserGenConfigRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserGenConfigRequest.Unmarshal(m, b)
 }
 func (m *UserGenConfigRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserGenConfigRequest.Marshal(b, m, deterministic)
 }
-func (m *UserGenConfigRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserGenConfigRequest.Merge(m, src)
+func (dst *UserGenConfigRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserGenConfigRequest.Merge(dst, src)
 }
 func (m *UserGenConfigRequest) XXX_Size() int {
 	return xxx_messageInfo_UserGenConfigRequest.Size(m)
@@ -416,17 +421,16 @@ func (m *UserResponse) Reset()         { *m = UserResponse{} }
 func (m *UserResponse) String() string { return proto.CompactTextString(m) }
 func (*UserResponse) ProtoMessage()    {}
 func (*UserResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{6}
+	return fileDescriptor_user_32c669a016e64e35, []int{6}
 }
-
 func (m *UserResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserResponse.Unmarshal(m, b)
 }
 func (m *UserResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserResponse.Marshal(b, m, deterministic)
 }
-func (m *UserResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserResponse.Merge(m, src)
+func (dst *UserResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserResponse.Merge(dst, src)
 }
 func (m *UserResponse) XXX_Size() int {
 	return xxx_messageInfo_UserResponse.Size(m)
@@ -458,6 +462,7 @@ type UserResponse_User struct {
 	BytesSent            uint64   `protobuf:"varint,11,opt,name=bytes_sent,json=bytesSent,proto3" json:"bytes_sent,omitempty"`
 	BytesReceived        uint64   `protobuf:"varint,12,opt,name=bytes_received,json=bytesReceived,proto3" json:"bytes_received,omitempty"`
 	ExpiresAt            string   `protobuf:"bytes,13,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
+	Description          string   `protobuf:"bytes,14,opt,name=description,proto3" json:"description,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -467,17 +472,16 @@ func (m *UserResponse_User) Reset()         { *m = UserResponse_User{} }
 func (m *UserResponse_User) String() string { return proto.CompactTextString(m) }
 func (*UserResponse_User) ProtoMessage()    {}
 func (*UserResponse_User) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{6, 0}
+	return fileDescriptor_user_32c669a016e64e35, []int{6, 0}
 }
-
 func (m *UserResponse_User) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserResponse_User.Unmarshal(m, b)
 }
 func (m *UserResponse_User) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserResponse_User.Marshal(b, m, deterministic)
 }
-func (m *UserResponse_User) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserResponse_User.Merge(m, src)
+func (dst *UserResponse_User) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserResponse_User.Merge(dst, src)
 }
 func (m *UserResponse_User) XXX_Size() int {
 	return xxx_messageInfo_UserResponse_User.Size(m)
@@ -579,6 +583,13 @@ func (m *UserResponse_User) GetExpiresAt() string {
 	return ""
 }
 
+func (m *UserResponse_User) GetDescription() string {
+	if m != nil {
+		return m.Description
+	}
+	return ""
+}
+
 type UserGenConfigResponse struct {
 	ClientConfig         string   `protobuf:"bytes,1,opt,name=client_config,json=clientConfig,proto3" json:"client_config,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -590,17 +601,16 @@ func (m *UserGenConfigResponse) Reset()         { *m = UserGenConfigResponse{} }
 func (m *UserGenConfigResponse) String() string { return proto.CompactTextString(m) }
 func (*UserGenConfigResponse) ProtoMessage()    {}
 func (*UserGenConfigResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_116e343673f7ffaf, []int{7}
+	return fileDescriptor_user_32c669a016e64e35, []int{7}
 }
-
 func (m *UserGenConfigResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_UserGenConfigResponse.Unmarshal(m, b)
 }
 func (m *UserGenConfigResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_UserGenConfigResponse.Marshal(b, m, deterministic)
 }
-func (m *UserGenConfigResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UserGenConfigResponse.Merge(m, src)
+func (dst *UserGenConfigResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserGenConfigResponse.Merge(dst, src)
 }
 func (m *UserGenConfigResponse) XXX_Size() int {
 	return xxx_messageInfo_UserGenConfigResponse.Size(m)
@@ -619,9 +629,6 @@ func (m *UserGenConfigResponse) GetClientConfig() string {
 }
 
 func init() {
-	proto.RegisterEnum("pb.UserUpdateRequest_GWPref", UserUpdateRequest_GWPref_name, UserUpdateRequest_GWPref_value)
-	proto.RegisterEnum("pb.UserUpdateRequest_StaticPref", UserUpdateRequest_StaticPref_name, UserUpdateRequest_StaticPref_value)
-	proto.RegisterEnum("pb.UserUpdateRequest_AdminPref", UserUpdateRequest_AdminPref_name, UserUpdateRequest_AdminPref_value)
 	proto.RegisterType((*UserListRequest)(nil), "pb.UserListRequest")
 	proto.RegisterType((*UserCreateRequest)(nil), "pb.UserCreateRequest")
 	proto.RegisterType((*UserUpdateRequest)(nil), "pb.UserUpdateRequest")
@@ -631,64 +638,9 @@ func init() {
 	proto.RegisterType((*UserResponse)(nil), "pb.UserResponse")
 	proto.RegisterType((*UserResponse_User)(nil), "pb.UserResponse.User")
 	proto.RegisterType((*UserGenConfigResponse)(nil), "pb.UserGenConfigResponse")
-}
-
-func init() { proto.RegisterFile("user.proto", fileDescriptor_116e343673f7ffaf) }
-
-var fileDescriptor_116e343673f7ffaf = []byte{
-	// 825 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xdd, 0x6e, 0xe3, 0x44,
-	0x14, 0x80, 0xeb, 0xc4, 0x71, 0xe3, 0x93, 0xb4, 0x75, 0xa7, 0x2d, 0xeb, 0x86, 0x5d, 0xc8, 0x1a,
-	0x01, 0xd1, 0x22, 0x25, 0x50, 0xf6, 0x02, 0xad, 0x10, 0x52, 0xd4, 0x85, 0x50, 0x09, 0x9c, 0xc5,
-	0xd9, 0x55, 0x2f, 0x2d, 0xc7, 0x3e, 0x09, 0x23, 0xa5, 0x63, 0x33, 0x33, 0x49, 0xe0, 0x16, 0x89,
-	0x27, 0x80, 0x0b, 0x5e, 0x84, 0x27, 0x41, 0xe2, 0x09, 0x78, 0x10, 0x34, 0x33, 0x4e, 0x42, 0x4a,
-	0x16, 0xe5, 0x62, 0xef, 0xe6, 0xfc, 0x7d, 0x73, 0x3c, 0xe7, 0xc7, 0x00, 0x73, 0x81, 0xbc, 0x5b,
-	0xf0, 0x5c, 0xe6, 0xa4, 0x52, 0x8c, 0x5b, 0x0f, 0xa7, 0x79, 0x3e, 0x9d, 0x61, 0x2f, 0x29, 0x68,
-	0x2f, 0x61, 0x2c, 0x97, 0x89, 0xa4, 0x39, 0x13, 0xc6, 0x23, 0x38, 0x85, 0x93, 0x57, 0x02, 0xf9,
-	0x37, 0x54, 0xc8, 0x08, 0x7f, 0x98, 0xa3, 0x90, 0xc1, 0x6f, 0x16, 0x9c, 0x2a, 0xdd, 0x35, 0xc7,
-	0x44, 0x62, 0xa9, 0x25, 0x2d, 0xa8, 0x2b, 0x30, 0x4b, 0xee, 0xd0, 0xb7, 0xda, 0x56, 0xc7, 0x8d,
-	0xd6, 0xb2, 0xb2, 0x15, 0x89, 0x10, 0xcb, 0x9c, 0x67, 0x7e, 0xc5, 0xd8, 0x56, 0x32, 0x39, 0x83,
-	0x1a, 0xcb, 0xe3, 0xe9, 0xd2, 0xaf, 0xb6, 0xad, 0x4e, 0x3d, 0xb2, 0x59, 0x3e, 0x58, 0x92, 0x07,
-	0x70, 0xf8, 0x7d, 0x2e, 0x64, 0x4c, 0x33, 0xdf, 0x6e, 0x5b, 0x9d, 0xa3, 0xc8, 0x51, 0xe2, 0x4d,
-	0x46, 0x2e, 0xa1, 0x4e, 0x45, 0x9c, 0x64, 0x77, 0x94, 0xf9, 0x35, 0x1d, 0x70, 0x48, 0x45, 0x5f,
-	0x89, 0xc1, 0x1f, 0x55, 0x93, 0xd6, 0xab, 0x22, 0x7b, 0x03, 0x69, 0x3d, 0x05, 0x67, 0xba, 0x2c,
-	0x38, 0x4e, 0x74, 0x5e, 0xc7, 0x57, 0x0f, 0xbb, 0xc5, 0xb8, 0xfb, 0x1f, 0x7c, 0x77, 0x70, 0xfb,
-	0x82, 0xe3, 0x24, 0x2a, 0x7d, 0x5f, 0x9f, 0x77, 0x1f, 0x1a, 0x42, 0x3d, 0x6c, 0x1a, 0x6b, 0x66,
-	0x4d, 0x33, 0xdb, 0xbb, 0x99, 0x23, 0xed, 0xa8, 0xb9, 0x20, 0xd6, 0x67, 0xf2, 0x05, 0x80, 0xfe,
-	0x6e, 0x43, 0x70, 0x34, 0xe1, 0xdd, 0xdd, 0x04, 0xfd, 0x20, 0x1a, 0xe0, 0x26, 0xab, 0x63, 0xf0,
-	0x01, 0x38, 0x26, 0x5b, 0x02, 0xe0, 0x84, 0xc3, 0x17, 0xd1, 0x97, 0x5f, 0x79, 0x07, 0xa4, 0x0e,
-	0x76, 0x38, 0x1c, 0xdc, 0x7a, 0x16, 0x71, 0xa0, 0x32, 0xb8, 0xf5, 0x2a, 0xc1, 0x67, 0x00, 0x9b,
-	0x0c, 0x88, 0x07, 0x4d, 0xe3, 0x3b, 0x7a, 0xd9, 0x7f, 0x79, 0x73, 0xed, 0x1d, 0x90, 0x26, 0xd4,
-	0xc3, 0x61, 0x29, 0x59, 0x8a, 0x55, 0x9e, 0x2b, 0xc1, 0x53, 0x70, 0xd7, 0x37, 0x93, 0x13, 0x68,
-	0x98, 0xc0, 0xfe, 0xf3, 0x6f, 0x6f, 0x42, 0xef, 0x80, 0x34, 0xe0, 0x30, 0x1c, 0x1a, 0xc1, 0x22,
-	0x2e, 0xd4, 0xcc, 0xb1, 0x12, 0xf4, 0x4c, 0xd9, 0x9e, 0xe3, 0x0c, 0xf7, 0x2a, 0x5b, 0xd0, 0x05,
-	0x4f, 0x05, 0x44, 0xc8, 0x70, 0xb9, 0x8f, 0xff, 0x15, 0x9c, 0x2b, 0xff, 0x01, 0xb2, 0xeb, 0x9c,
-	0x4d, 0xe8, 0x74, 0x9f, 0x98, 0xbf, 0xaa, 0xd0, 0x34, 0x97, 0x88, 0x22, 0x67, 0x02, 0xc9, 0x47,
-	0x50, 0x53, 0x46, 0xe1, 0x5b, 0xed, 0x6a, 0xa7, 0x71, 0x75, 0xb1, 0x7a, 0xf8, 0x95, 0x83, 0x11,
-	0x8c, 0x4f, 0xeb, 0xf7, 0x2a, 0xd8, 0x4a, 0xfe, 0xdf, 0xee, 0xfb, 0x18, 0xce, 0x05, 0xf2, 0x05,
-	0xf2, 0x58, 0x20, 0xa7, 0xc9, 0x2c, 0x66, 0xf3, 0xbb, 0x31, 0xf2, 0xb2, 0x13, 0x89, 0xb1, 0x8d,
-	0xb4, 0x29, 0xd4, 0x16, 0x42, 0xc0, 0x4e, 0x91, 0x4b, 0xdd, 0x91, 0x6e, 0xa4, 0xcf, 0xe4, 0x11,
-	0x40, 0xaa, 0xe7, 0x30, 0x8b, 0x13, 0xa9, 0x9b, 0xce, 0x8d, 0xdc, 0x52, 0xd3, 0x97, 0xe4, 0x02,
-	0x1c, 0x5a, 0xc4, 0x0c, 0xa5, 0x6e, 0x39, 0x37, 0xaa, 0xd1, 0x22, 0x44, 0xb9, 0x19, 0x3a, 0x67,
-	0xf7, 0xd0, 0x1d, 0xbe, 0x76, 0xe8, 0xea, 0x5b, 0x43, 0x47, 0x1e, 0x43, 0x93, 0x8a, 0x38, 0xcd,
-	0x19, 0xc3, 0x54, 0x62, 0xe6, 0xbb, 0xda, 0xdc, 0xa0, 0xe2, 0x7a, 0xa5, 0x22, 0x1f, 0xc2, 0xc9,
-	0xda, 0x1e, 0x0b, 0xca, 0x52, 0xf4, 0x41, 0xe7, 0x72, 0xbc, 0x56, 0x8f, 0x94, 0x56, 0x7d, 0xca,
-	0xf8, 0x27, 0x89, 0x22, 0x16, 0xc8, 0xa4, 0xdf, 0x68, 0x5b, 0x1d, 0x3b, 0x72, 0xb5, 0x66, 0x84,
-	0x4c, 0x92, 0xf7, 0xe1, 0xd8, 0x98, 0x39, 0xa6, 0x48, 0x17, 0x98, 0xf9, 0x4d, 0xed, 0x72, 0xa4,
-	0xb5, 0x51, 0xa9, 0x54, 0x14, 0xfc, 0xb1, 0xa0, 0x1c, 0x85, 0x7a, 0x90, 0x23, 0xf3, 0x20, 0xa5,
-	0xa6, 0x2f, 0x83, 0xcf, 0xe1, 0xe2, 0x5e, 0x33, 0x94, 0x05, 0x7e, 0x0f, 0x8e, 0xd2, 0x19, 0x45,
-	0x26, 0xd5, 0xd7, 0x4c, 0xe8, 0xb4, 0xac, 0x57, 0xd3, 0x28, 0x8d, 0xf3, 0xd5, 0x2f, 0x36, 0x34,
-	0x54, 0xf8, 0x08, 0xf9, 0x82, 0xa6, 0x48, 0xbe, 0x06, 0x5b, 0x6d, 0x46, 0x72, 0xb6, 0x6a, 0x87,
-	0x7f, 0xed, 0xc9, 0x96, 0x77, 0xbf, 0x47, 0x82, 0xcb, 0x9f, 0xff, 0xfc, 0xfb, 0xd7, 0xca, 0x19,
-	0x39, 0xd5, 0xcb, 0x76, 0xf1, 0x49, 0x4f, 0x35, 0x43, 0x6f, 0xa6, 0x08, 0xdf, 0x81, 0x63, 0xf6,
-	0x29, 0x59, 0xb7, 0xd6, 0xd6, 0x7e, 0xdd, 0x41, 0x7b, 0x47, 0xd3, 0xfc, 0xe0, 0x6c, 0x8b, 0x66,
-	0x6a, 0xff, 0xcc, 0x7a, 0xa2, 0x90, 0x66, 0x2d, 0x6c, 0x90, 0x5b, 0x6b, 0x62, 0x6f, 0xe4, 0x5c,
-	0x47, 0x95, 0x48, 0x33, 0xa7, 0x1b, 0xe4, 0xd6, 0xdc, 0xee, 0x8d, 0xcc, 0x74, 0x94, 0x42, 0x86,
-	0x50, 0xd3, 0x93, 0x4c, 0xce, 0x37, 0xa1, 0x9b, 0xc1, 0xde, 0x01, 0x7c, 0xa4, 0x81, 0x0f, 0x02,
-	0xb2, 0x05, 0xe4, 0x2a, 0x48, 0xf1, 0x52, 0x70, 0xd7, 0xc5, 0x25, 0xfe, 0x2a, 0xfa, 0xfe, 0xf0,
-	0xb7, 0x2e, 0x77, 0x58, 0xca, 0x0b, 0x1e, 0xeb, 0x0b, 0xde, 0x0e, 0xde, 0xda, 0xba, 0x60, 0x8a,
-	0xcc, 0x34, 0xc6, 0x33, 0xeb, 0xc9, 0xd8, 0xd1, 0x3f, 0xc7, 0x4f, 0xff, 0x09, 0x00, 0x00, 0xff,
-	0xff, 0x42, 0xdb, 0x7d, 0x5f, 0x4c, 0x07, 0x00, 0x00,
+	proto.RegisterEnum("pb.UserUpdateRequest_GWPref", UserUpdateRequest_GWPref_name, UserUpdateRequest_GWPref_value)
+	proto.RegisterEnum("pb.UserUpdateRequest_StaticPref", UserUpdateRequest_StaticPref_name, UserUpdateRequest_StaticPref_value)
+	proto.RegisterEnum("pb.UserUpdateRequest_AdminPref", UserUpdateRequest_AdminPref_name, UserUpdateRequest_AdminPref_value)
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -927,3 +879,62 @@ var _UserService_serviceDesc = grpc.ServiceDesc{
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "user.proto",
 }
+
+func init() { proto.RegisterFile("user.proto", fileDescriptor_user_32c669a016e64e35) }
+
+var fileDescriptor_user_32c669a016e64e35 = []byte{
+	// 845 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x55, 0xcf, 0x6e, 0xf3, 0x44,
+	0x10, 0x27, 0x89, 0xe3, 0xc4, 0xe3, 0x24, 0x4d, 0x37, 0x2d, 0x75, 0x43, 0x0b, 0xad, 0x11, 0x50,
+	0x81, 0x94, 0x40, 0xe8, 0x01, 0x21, 0x84, 0x14, 0xa5, 0x10, 0x2a, 0x81, 0x53, 0x9c, 0x56, 0x3d,
+	0x5a, 0x8e, 0xbd, 0x0d, 0x2b, 0xa5, 0x6b, 0xe3, 0x75, 0x12, 0xb8, 0x22, 0xf1, 0x04, 0xbc, 0x0b,
+	0x07, 0x5e, 0x83, 0x03, 0x2f, 0xc0, 0x43, 0x7c, 0xc7, 0x6f, 0xff, 0x38, 0x49, 0x93, 0xa6, 0x9f,
+	0x72, 0xf8, 0x4e, 0xde, 0x99, 0xf9, 0xcd, 0x6f, 0x66, 0x67, 0x67, 0xc6, 0x00, 0x53, 0x86, 0x93,
+	0x56, 0x9c, 0x44, 0x69, 0x84, 0xf2, 0xf1, 0xa8, 0x79, 0x32, 0x8e, 0xa2, 0xf1, 0x04, 0xb7, 0xfd,
+	0x98, 0xb4, 0x7d, 0x4a, 0xa3, 0xd4, 0x4f, 0x49, 0x44, 0x99, 0x42, 0xd8, 0xfb, 0xb0, 0x77, 0xc7,
+	0xf1, 0x3f, 0x12, 0x96, 0xba, 0xf8, 0xd7, 0x29, 0x66, 0xa9, 0xfd, 0x77, 0x0e, 0xf6, 0x85, 0xae,
+	0x97, 0x60, 0x3f, 0xc5, 0x99, 0x16, 0x35, 0xa1, 0x2c, 0x88, 0xa9, 0xff, 0x88, 0xad, 0xdc, 0x59,
+	0xee, 0xc2, 0x70, 0x97, 0xb2, 0xb0, 0xc5, 0x3e, 0x63, 0xf3, 0x28, 0x09, 0xad, 0xbc, 0xb2, 0x2d,
+	0x64, 0xd4, 0x80, 0x22, 0x8d, 0xbc, 0xf1, 0xdc, 0x2a, 0x70, 0x43, 0xd9, 0xd5, 0x68, 0xd4, 0x9f,
+	0xa3, 0x23, 0x28, 0xfd, 0x12, 0xb1, 0xd4, 0x23, 0xa1, 0xa5, 0x71, 0x75, 0xd5, 0xd5, 0x85, 0x78,
+	0x1d, 0xa2, 0x63, 0x28, 0x13, 0xe6, 0xf9, 0xe1, 0x23, 0xa1, 0x56, 0x51, 0x3a, 0x94, 0x08, 0xeb,
+	0x0a, 0x11, 0x9d, 0x81, 0x19, 0x62, 0x16, 0x24, 0x24, 0x16, 0xf9, 0x5b, 0xba, 0x8c, 0xf3, 0x54,
+	0x65, 0xff, 0x57, 0x50, 0x89, 0xdf, 0xc5, 0xe1, 0x5b, 0x48, 0xfc, 0x12, 0xf4, 0xf1, 0x3c, 0x4e,
+	0xf0, 0x83, 0xcc, 0xbc, 0xd6, 0x39, 0x69, 0xc5, 0xa3, 0xd6, 0x33, 0xfa, 0x56, 0xff, 0xfe, 0x86,
+	0x63, 0xdc, 0x0c, 0xfb, 0xf2, 0xcd, 0xba, 0x60, 0x32, 0x51, 0xfa, 0xc0, 0x93, 0x9c, 0x45, 0xc9,
+	0x79, 0xb6, 0x9d, 0x73, 0x28, 0x81, 0x92, 0x17, 0xd8, 0xf2, 0x8c, 0xbe, 0x05, 0x90, 0x95, 0x51,
+	0x0c, 0xba, 0x64, 0xf8, 0x60, 0x3b, 0x83, 0x2c, 0x99, 0x24, 0x30, 0xfc, 0xc5, 0x71, 0xb3, 0x82,
+	0xa5, 0xe7, 0x15, 0xfc, 0x18, 0x74, 0x75, 0x1f, 0x04, 0xa0, 0x3b, 0x83, 0x1b, 0xf7, 0xbb, 0xef,
+	0xeb, 0xef, 0xa0, 0x32, 0x68, 0xce, 0xa0, 0x7f, 0x5f, 0xcf, 0x21, 0x1d, 0xf2, 0xfc, 0x9b, 0xb7,
+	0xbf, 0x02, 0x58, 0xe5, 0x88, 0xea, 0x50, 0x51, 0xd8, 0xe1, 0x6d, 0xf7, 0xf6, 0xba, 0xc7, 0x3d,
+	0x2a, 0x50, 0x76, 0x06, 0x99, 0x94, 0x13, 0x5c, 0xd9, 0x39, 0x6f, 0x5f, 0x82, 0xb1, 0xcc, 0x0d,
+	0xed, 0x81, 0xa9, 0x1c, 0xbb, 0x57, 0x3f, 0x5d, 0x3b, 0xdc, 0xcf, 0x84, 0x92, 0x33, 0x50, 0x42,
+	0x0e, 0x19, 0x50, 0x54, 0xc7, 0xbc, 0xdd, 0x56, 0x0f, 0x7b, 0x85, 0x27, 0x78, 0xa7, 0x87, 0xb5,
+	0x5b, 0x50, 0x17, 0x0e, 0x2e, 0xa6, 0x78, 0xbe, 0x0b, 0xbe, 0x03, 0x07, 0x02, 0xdf, 0xc7, 0xb4,
+	0x17, 0xd1, 0x07, 0x32, 0xde, 0xc5, 0xe7, 0x55, 0x01, 0x2a, 0x2a, 0x08, 0x8b, 0xf9, 0x40, 0x61,
+	0xf4, 0x19, 0x14, 0x85, 0x91, 0x71, 0x64, 0xe1, 0xc2, 0xec, 0x1c, 0x2e, 0x9e, 0x66, 0x01, 0x50,
+	0x82, 0xc2, 0x34, 0xff, 0x29, 0x80, 0x26, 0xe4, 0x37, 0xf6, 0xe7, 0xe7, 0x70, 0xc0, 0x8f, 0x33,
+	0x9c, 0x78, 0xfc, 0x43, 0xfc, 0x89, 0x47, 0xa7, 0x8f, 0x23, 0x9c, 0x64, 0xbd, 0x8a, 0x94, 0x6d,
+	0x28, 0x4d, 0x8e, 0xb4, 0x20, 0x04, 0x5a, 0x80, 0x93, 0x54, 0xf6, 0xac, 0xe1, 0xca, 0x33, 0x3a,
+	0x05, 0x08, 0xe4, 0x2c, 0x87, 0x9e, 0x9f, 0xca, 0xb6, 0x34, 0x5c, 0x23, 0xd3, 0x74, 0x53, 0x74,
+	0x08, 0x3a, 0x89, 0x3d, 0x8a, 0x53, 0xd9, 0x94, 0x86, 0x5b, 0x24, 0xb1, 0x83, 0xd3, 0xd5, 0xe0,
+	0xea, 0xdb, 0x07, 0xb7, 0xf4, 0xe2, 0xe0, 0x96, 0xd7, 0x07, 0xf7, 0x1c, 0x2a, 0xdc, 0x14, 0x44,
+	0x94, 0xe2, 0x80, 0x47, 0xb4, 0x0c, 0x69, 0x36, 0x09, 0xeb, 0x2d, 0x54, 0xe8, 0x13, 0xd8, 0x5b,
+	0xda, 0x3d, 0x46, 0x68, 0x80, 0x2d, 0x90, 0xb9, 0xd4, 0x96, 0xea, 0xa1, 0xd0, 0x8a, 0xab, 0x8c,
+	0x7e, 0x4f, 0x31, 0xe3, 0xf5, 0xa0, 0xa9, 0x65, 0x72, 0x8c, 0xe6, 0x1a, 0x52, 0x33, 0xe4, 0x0a,
+	0xf4, 0x11, 0xd4, 0x94, 0x39, 0xc1, 0x01, 0x26, 0x33, 0x1e, 0xac, 0x22, 0x21, 0x55, 0xa9, 0x75,
+	0x33, 0xa5, 0x60, 0xc1, 0xbf, 0xc5, 0x24, 0xe1, 0x40, 0x5e, 0x90, 0xaa, 0x2a, 0x48, 0xa6, 0xe1,
+	0x05, 0xd9, 0x98, 0x93, 0xda, 0xf3, 0x39, 0xf9, 0x06, 0x0e, 0x37, 0xda, 0x25, 0x6b, 0x81, 0x0f,
+	0xa1, 0x1a, 0x4c, 0x08, 0x4f, 0x45, 0xdc, 0x97, 0x1b, 0xb2, 0x17, 0xad, 0x28, 0xa5, 0x02, 0x77,
+	0xfe, 0xd4, 0xc0, 0x14, 0xee, 0xfc, 0xe1, 0x66, 0x84, 0x5f, 0xea, 0x07, 0xd0, 0xc4, 0xfe, 0x45,
+	0x8d, 0x45, 0xc3, 0x3c, 0xd9, 0xc6, 0xcd, 0xfa, 0x66, 0x17, 0xd9, 0xc7, 0x7f, 0xfc, 0xfb, 0xff,
+	0x5f, 0xf9, 0x06, 0xda, 0x97, 0x2b, 0x7d, 0xf6, 0x45, 0x5b, 0xb4, 0x4b, 0x7b, 0x22, 0x18, 0x7e,
+	0x06, 0x5d, 0x6d, 0x6d, 0xb4, 0x6c, 0xbe, 0xb5, 0x2d, 0xbe, 0x85, 0xed, 0x7d, 0xc9, 0x66, 0xd9,
+	0x8d, 0x35, 0x36, 0xd5, 0x1d, 0x5f, 0xe7, 0x3e, 0x15, 0x94, 0x6a, 0xb5, 0xac, 0x28, 0xd7, 0x56,
+	0xcd, 0xce, 0x94, 0x53, 0xe9, 0x95, 0x51, 0xaa, 0x49, 0x5e, 0x51, 0xae, 0x4d, 0xf6, 0xce, 0x94,
+	0xa1, 0xf4, 0x12, 0x94, 0x0e, 0x14, 0xe5, 0xac, 0xa3, 0x83, 0x95, 0xeb, 0x6a, 0xf4, 0xb7, 0x10,
+	0x9e, 0x4a, 0xc2, 0x23, 0x1b, 0xad, 0x11, 0x26, 0xc2, 0x49, 0xf0, 0x05, 0x60, 0x2c, 0x1f, 0x17,
+	0x59, 0x0b, 0xef, 0xcd, 0xf5, 0xd0, 0x3c, 0xde, 0x62, 0xc9, 0x02, 0x9c, 0xcb, 0x00, 0xef, 0xd9,
+	0xef, 0xae, 0x05, 0x18, 0x63, 0xaa, 0x1a, 0x83, 0x07, 0x19, 0xe9, 0xf2, 0x17, 0xfc, 0xe5, 0xeb,
+	0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0xfc, 0x4a, 0x18, 0xb2, 0x07, 0x00, 0x00,
+}

+ 6 - 6
api/pb/user.pb.gw.go

@@ -284,17 +284,17 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 }
 
 var (
-	pattern_UserService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "list"}, ""))
+	pattern_UserService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "list"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_UserService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "create"}, ""))
+	pattern_UserService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "create"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_UserService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "update"}, ""))
+	pattern_UserService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "update"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_UserService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "delete"}, ""))
+	pattern_UserService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "delete"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_UserService_Renew_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "renew"}, ""))
+	pattern_UserService_Renew_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "renew"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_UserService_GenConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "genconfig"}, ""))
+	pattern_UserService_GenConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "user", "genconfig"}, "", runtime.AssumeColonVerbOpt(true)))
 )
 
 var (

+ 3 - 0
api/pb/user.proto

@@ -14,6 +14,7 @@ message UserCreateRequest {
   bool no_gw = 3;
   uint32 host_id = 4;
   bool is_admin = 5;
+  string description = 6;
 }
 
 message UserUpdateRequest {
@@ -38,6 +39,7 @@ message UserUpdateRequest {
     ADMIN = 2;
   }
   AdminPref admin_pref = 6;
+  string description = 7;
 }
 
 
@@ -111,6 +113,7 @@ message UserResponse {
     uint64 bytes_sent = 11;
     uint64 bytes_received = 12;
     string expires_at = 13;
+    string description = 14;
   }
 
   repeated User users = 1;

+ 78 - 88
api/pb/vpn.pb.go

@@ -3,13 +3,14 @@
 
 package pb
 
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
 import (
-	context "context"
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	_ "google.golang.org/genproto/googleapis/api/annotations"
+	context "golang.org/x/net/context"
 	grpc "google.golang.org/grpc"
-	math "math"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -21,7 +22,7 @@ var _ = math.Inf
 // is compatible with the proto package it is being compiled against.
 // A compilation error at this line likely means your copy of the
 // proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 type VPNProto int32
 
@@ -36,7 +37,6 @@ var VPNProto_name = map[int32]string{
 	1: "UDP",
 	2: "TCP",
 }
-
 var VPNProto_value = map[string]int32{
 	"NOPREF": 0,
 	"UDP":    1,
@@ -46,9 +46,8 @@ var VPNProto_value = map[string]int32{
 func (x VPNProto) String() string {
 	return proto.EnumName(VPNProto_name, int32(x))
 }
-
 func (VPNProto) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{0}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{0}
 }
 
 type VPNStatusRequest struct {
@@ -61,17 +60,16 @@ func (m *VPNStatusRequest) Reset()         { *m = VPNStatusRequest{} }
 func (m *VPNStatusRequest) String() string { return proto.CompactTextString(m) }
 func (*VPNStatusRequest) ProtoMessage()    {}
 func (*VPNStatusRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{0}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{0}
 }
-
 func (m *VPNStatusRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNStatusRequest.Unmarshal(m, b)
 }
 func (m *VPNStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNStatusRequest.Marshal(b, m, deterministic)
 }
-func (m *VPNStatusRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNStatusRequest.Merge(m, src)
+func (dst *VPNStatusRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNStatusRequest.Merge(dst, src)
 }
 func (m *VPNStatusRequest) XXX_Size() int {
 	return xxx_messageInfo_VPNStatusRequest.Size(m)
@@ -100,17 +98,16 @@ func (m *VPNInitRequest) Reset()         { *m = VPNInitRequest{} }
 func (m *VPNInitRequest) String() string { return proto.CompactTextString(m) }
 func (*VPNInitRequest) ProtoMessage()    {}
 func (*VPNInitRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{1}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{1}
 }
-
 func (m *VPNInitRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNInitRequest.Unmarshal(m, b)
 }
 func (m *VPNInitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNInitRequest.Marshal(b, m, deterministic)
 }
-func (m *VPNInitRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNInitRequest.Merge(m, src)
+func (dst *VPNInitRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNInitRequest.Merge(dst, src)
 }
 func (m *VPNInitRequest) XXX_Size() int {
 	return xxx_messageInfo_VPNInitRequest.Size(m)
@@ -189,17 +186,16 @@ func (m *VPNUpdateRequest) Reset()         { *m = VPNUpdateRequest{} }
 func (m *VPNUpdateRequest) String() string { return proto.CompactTextString(m) }
 func (*VPNUpdateRequest) ProtoMessage()    {}
 func (*VPNUpdateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{2}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{2}
 }
-
 func (m *VPNUpdateRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNUpdateRequest.Unmarshal(m, b)
 }
 func (m *VPNUpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNUpdateRequest.Marshal(b, m, deterministic)
 }
-func (m *VPNUpdateRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNUpdateRequest.Merge(m, src)
+func (dst *VPNUpdateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNUpdateRequest.Merge(dst, src)
 }
 func (m *VPNUpdateRequest) XXX_Size() int {
 	return xxx_messageInfo_VPNUpdateRequest.Size(m)
@@ -234,17 +230,16 @@ func (m *VPNRestartRequest) Reset()         { *m = VPNRestartRequest{} }
 func (m *VPNRestartRequest) String() string { return proto.CompactTextString(m) }
 func (*VPNRestartRequest) ProtoMessage()    {}
 func (*VPNRestartRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{3}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{3}
 }
-
 func (m *VPNRestartRequest) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNRestartRequest.Unmarshal(m, b)
 }
 func (m *VPNRestartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNRestartRequest.Marshal(b, m, deterministic)
 }
-func (m *VPNRestartRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNRestartRequest.Merge(m, src)
+func (dst *VPNRestartRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNRestartRequest.Merge(dst, src)
 }
 func (m *VPNRestartRequest) XXX_Size() int {
 	return xxx_messageInfo_VPNRestartRequest.Size(m)
@@ -278,17 +273,16 @@ func (m *VPNStatusResponse) Reset()         { *m = VPNStatusResponse{} }
 func (m *VPNStatusResponse) String() string { return proto.CompactTextString(m) }
 func (*VPNStatusResponse) ProtoMessage()    {}
 func (*VPNStatusResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{4}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{4}
 }
-
 func (m *VPNStatusResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNStatusResponse.Unmarshal(m, b)
 }
 func (m *VPNStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNStatusResponse.Marshal(b, m, deterministic)
 }
-func (m *VPNStatusResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNStatusResponse.Merge(m, src)
+func (dst *VPNStatusResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNStatusResponse.Merge(dst, src)
 }
 func (m *VPNStatusResponse) XXX_Size() int {
 	return xxx_messageInfo_VPNStatusResponse.Size(m)
@@ -400,17 +394,16 @@ func (m *VPNInitResponse) Reset()         { *m = VPNInitResponse{} }
 func (m *VPNInitResponse) String() string { return proto.CompactTextString(m) }
 func (*VPNInitResponse) ProtoMessage()    {}
 func (*VPNInitResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{5}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{5}
 }
-
 func (m *VPNInitResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNInitResponse.Unmarshal(m, b)
 }
 func (m *VPNInitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNInitResponse.Marshal(b, m, deterministic)
 }
-func (m *VPNInitResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNInitResponse.Merge(m, src)
+func (dst *VPNInitResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNInitResponse.Merge(dst, src)
 }
 func (m *VPNInitResponse) XXX_Size() int {
 	return xxx_messageInfo_VPNInitResponse.Size(m)
@@ -431,17 +424,16 @@ func (m *VPNUpdateResponse) Reset()         { *m = VPNUpdateResponse{} }
 func (m *VPNUpdateResponse) String() string { return proto.CompactTextString(m) }
 func (*VPNUpdateResponse) ProtoMessage()    {}
 func (*VPNUpdateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{6}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{6}
 }
-
 func (m *VPNUpdateResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNUpdateResponse.Unmarshal(m, b)
 }
 func (m *VPNUpdateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNUpdateResponse.Marshal(b, m, deterministic)
 }
-func (m *VPNUpdateResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNUpdateResponse.Merge(m, src)
+func (dst *VPNUpdateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNUpdateResponse.Merge(dst, src)
 }
 func (m *VPNUpdateResponse) XXX_Size() int {
 	return xxx_messageInfo_VPNUpdateResponse.Size(m)
@@ -462,17 +454,16 @@ func (m *VPNRestartResponse) Reset()         { *m = VPNRestartResponse{} }
 func (m *VPNRestartResponse) String() string { return proto.CompactTextString(m) }
 func (*VPNRestartResponse) ProtoMessage()    {}
 func (*VPNRestartResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_75c5922f473942e1, []int{7}
+	return fileDescriptor_vpn_38c1de627905a14e, []int{7}
 }
-
 func (m *VPNRestartResponse) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_VPNRestartResponse.Unmarshal(m, b)
 }
 func (m *VPNRestartResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	return xxx_messageInfo_VPNRestartResponse.Marshal(b, m, deterministic)
 }
-func (m *VPNRestartResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_VPNRestartResponse.Merge(m, src)
+func (dst *VPNRestartResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VPNRestartResponse.Merge(dst, src)
 }
 func (m *VPNRestartResponse) XXX_Size() int {
 	return xxx_messageInfo_VPNRestartResponse.Size(m)
@@ -484,7 +475,6 @@ func (m *VPNRestartResponse) XXX_DiscardUnknown() {
 var xxx_messageInfo_VPNRestartResponse proto.InternalMessageInfo
 
 func init() {
-	proto.RegisterEnum("pb.VPNProto", VPNProto_name, VPNProto_value)
 	proto.RegisterType((*VPNStatusRequest)(nil), "pb.VPNStatusRequest")
 	proto.RegisterType((*VPNInitRequest)(nil), "pb.VPNInitRequest")
 	proto.RegisterType((*VPNUpdateRequest)(nil), "pb.VPNUpdateRequest")
@@ -493,52 +483,7 @@ func init() {
 	proto.RegisterType((*VPNInitResponse)(nil), "pb.VPNInitResponse")
 	proto.RegisterType((*VPNUpdateResponse)(nil), "pb.VPNUpdateResponse")
 	proto.RegisterType((*VPNRestartResponse)(nil), "pb.VPNRestartResponse")
-}
-
-func init() { proto.RegisterFile("vpn.proto", fileDescriptor_75c5922f473942e1) }
-
-var fileDescriptor_75c5922f473942e1 = []byte{
-	// 628 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x93, 0x4f, 0x6f, 0xd3, 0x4c,
-	0x10, 0xc6, 0x5f, 0x3b, 0xa9, 0x93, 0x4c, 0xff, 0xb9, 0xd3, 0xf4, 0xad, 0x09, 0x54, 0xaa, 0xcc,
-	0x25, 0xb4, 0x52, 0x23, 0xca, 0x8d, 0x0b, 0x2a, 0xa5, 0x48, 0x48, 0x55, 0x30, 0xa6, 0xcd, 0xd5,
-	0xda, 0x38, 0xdb, 0x62, 0x35, 0xf1, 0x2e, 0xbb, 0xeb, 0x08, 0xf5, 0xc8, 0x95, 0x23, 0x1f, 0x8d,
-	0x13, 0x9c, 0xf9, 0x20, 0xc8, 0x63, 0x3b, 0x75, 0x22, 0xb8, 0x8d, 0x7f, 0x33, 0x79, 0x34, 0x79,
-	0x9e, 0x59, 0xe8, 0xcc, 0x65, 0x7a, 0x22, 0x95, 0x30, 0x02, 0x6d, 0x39, 0xee, 0x3d, 0xb9, 0x15,
-	0xe2, 0x76, 0xca, 0x07, 0x4c, 0x26, 0x03, 0x96, 0xa6, 0xc2, 0x30, 0x93, 0x88, 0x54, 0x17, 0x13,
-	0x3e, 0x82, 0x3b, 0x0a, 0x86, 0x1f, 0x0d, 0x33, 0x99, 0x0e, 0xf9, 0xe7, 0x8c, 0x6b, 0xe3, 0x7f,
-	0xb3, 0x61, 0x6b, 0x14, 0x0c, 0xdf, 0xa5, 0x89, 0x29, 0x11, 0xf6, 0xa0, 0xfd, 0x49, 0x68, 0x93,
-	0xb2, 0x19, 0xf7, 0xac, 0x43, 0xab, 0xdf, 0x09, 0x17, 0xdf, 0x88, 0xd0, 0x94, 0x42, 0x19, 0xcf,
-	0x26, 0x4e, 0x35, 0x1e, 0x03, 0x90, 0x7e, 0x24, 0x15, 0xbf, 0xf1, 0x1a, 0x87, 0x56, 0x7f, 0xeb,
-	0x74, 0xe3, 0x44, 0x8e, 0x4f, 0x46, 0xc1, 0x30, 0xc8, 0x1b, 0x61, 0x87, 0xfa, 0x81, 0xe2, 0x37,
-	0xf8, 0x08, 0xda, 0x89, 0x8c, 0xc6, 0x53, 0x11, 0xdf, 0x79, 0x4d, 0x12, 0x69, 0x25, 0xf2, 0x75,
-	0xfe, 0x89, 0x2e, 0x34, 0x26, 0xa9, 0xf6, 0xd6, 0x88, 0xe6, 0x25, 0x3e, 0x03, 0xf7, 0x8e, 0x73,
-	0xc9, 0xa6, 0xc9, 0x9c, 0x47, 0x92, 0xab, 0x44, 0x4c, 0x3c, 0x87, 0xda, 0xdb, 0x0b, 0x1e, 0x10,
-	0xc6, 0x63, 0xd8, 0x79, 0x18, 0x35, 0xc9, 0x8c, 0x8b, 0xcc, 0x78, 0x2d, 0x9a, 0x7d, 0xd0, 0xb8,
-	0x2a, 0x38, 0xee, 0x43, 0x2b, 0xd3, 0x3c, 0x9a, 0xde, 0x0b, 0xaf, 0x7d, 0x68, 0xf5, 0xdb, 0xa1,
-	0x93, 0x69, 0x7e, 0x79, 0x2f, 0xfc, 0x57, 0xe4, 0xd0, 0xb5, 0x9c, 0x30, 0xc3, 0x2b, 0x3b, 0xea,
-	0x1b, 0x5b, 0x7f, 0xdd, 0xd8, 0x5e, 0x6c, 0xec, 0xef, 0xc2, 0xce, 0x28, 0x18, 0x86, 0x5c, 0x1b,
-	0xa6, 0x2a, 0x43, 0xfd, 0x9f, 0x36, 0xd1, 0xca, 0x78, 0x2d, 0x45, 0xaa, 0xc9, 0xca, 0x9a, 0xc5,
-	0x54, 0xe3, 0x53, 0xd8, 0xd4, 0x5c, 0x25, 0x6c, 0x1a, 0xa5, 0xd9, 0x6c, 0xcc, 0x55, 0x29, 0xbd,
-	0x51, 0xc0, 0x21, 0xb1, 0xa5, 0x7c, 0x1a, 0xff, 0xc8, 0xa7, 0x59, 0xcb, 0x07, 0xa1, 0x19, 0x73,
-	0x65, 0x4a, 0x63, 0xa9, 0xce, 0x1d, 0x88, 0x59, 0x44, 0xb8, 0x30, 0xd4, 0x89, 0xd9, 0x79, 0xde,
-	0x70, 0xa1, 0x91, 0xf2, 0xca, 0xb9, 0xbc, 0xcc, 0x7f, 0x3e, 0x63, 0xfa, 0x8e, 0x9c, 0xea, 0x84,
-	0x54, 0xe3, 0x01, 0x40, 0xac, 0x38, 0x33, 0x7c, 0x12, 0x31, 0xe3, 0x75, 0xa8, 0xd3, 0x29, 0xc9,
-	0x99, 0xc1, 0x2e, 0xac, 0x51, 0xe2, 0x1e, 0x50, 0xa7, 0xf8, 0xa8, 0xdc, 0x5a, 0x7f, 0xc8, 0xf7,
-	0x00, 0x80, 0x7f, 0x91, 0x89, 0xe2, 0x3a, 0x97, 0xd9, 0x28, 0x64, 0x4a, 0x72, 0x66, 0xd0, 0x87,
-	0xcd, 0x98, 0x45, 0xb5, 0x89, 0x4d, 0x9a, 0x58, 0x8f, 0xd9, 0x45, 0x35, 0xe3, 0xef, 0xc0, 0xf6,
-	0xe2, 0x7c, 0x0b, 0x63, 0xcb, 0x0c, 0xaa, 0x10, 0x4b, 0xd8, 0x05, 0xac, 0x07, 0x53, 0xd0, 0xa3,
-	0x3e, 0xb4, 0xab, 0x23, 0x45, 0x00, 0x67, 0xf8, 0x3e, 0x08, 0x2f, 0xde, 0xba, 0xff, 0x61, 0x0b,
-	0x1a, 0xd7, 0x6f, 0x02, 0xd7, 0xca, 0x8b, 0xab, 0xf3, 0xc0, 0xb5, 0x4f, 0x7f, 0xd9, 0x00, 0x79,
-	0x86, 0x5c, 0xcd, 0x93, 0x98, 0xe3, 0x07, 0x70, 0x8a, 0x38, 0xb1, 0x5b, 0x5e, 0xfa, 0xd2, 0xb3,
-	0xea, 0xed, 0xad, 0xd0, 0x72, 0x8b, 0xde, 0xd7, 0x1f, 0xbf, 0xbf, 0xdb, 0x5d, 0x44, 0x7a, 0xa1,
-	0xf3, 0xe7, 0x83, 0xb9, 0x4c, 0x07, 0xba, 0x10, 0xba, 0x84, 0x66, 0xfe, 0x37, 0x10, 0xcb, 0x9f,
-	0xd6, 0x9e, 0x64, 0x6f, 0x77, 0x89, 0x95, 0x62, 0x8f, 0x49, 0x6c, 0xcf, 0x77, 0xeb, 0x62, 0x49,
-	0x9a, 0x98, 0x97, 0xd6, 0x11, 0x5e, 0x81, 0x53, 0x38, 0xb0, 0x58, 0x70, 0xe9, 0xaa, 0x17, 0x0b,
-	0xae, 0xd8, 0x74, 0x40, 0x9a, 0xfb, 0xfe, 0xd2, 0x82, 0x19, 0xcd, 0xe4, 0xaa, 0xd7, 0xd0, 0x2a,
-	0x2d, 0xc4, 0x4a, 0x60, 0xf9, 0xd6, 0x7b, 0xff, 0xaf, 0xe2, 0x95, 0x65, 0x77, 0xeb, 0xc2, 0xaa,
-	0x18, 0x1a, 0x3b, 0x74, 0x20, 0x2f, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0xba, 0x04, 0x57, 0xbd,
-	0xce, 0x04, 0x00, 0x00,
+	proto.RegisterEnum("pb.VPNProto", VPNProto_name, VPNProto_value)
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -711,3 +656,48 @@ var _VPNService_serviceDesc = grpc.ServiceDesc{
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "vpn.proto",
 }
+
+func init() { proto.RegisterFile("vpn.proto", fileDescriptor_vpn_38c1de627905a14e) }
+
+var fileDescriptor_vpn_38c1de627905a14e = []byte{
+	// 619 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x93, 0xcf, 0x6e, 0xd3, 0x40,
+	0x10, 0xc6, 0x89, 0x93, 0x3a, 0xc9, 0xf4, 0x9f, 0x3b, 0x4d, 0xa9, 0x09, 0x54, 0x42, 0xe6, 0x52,
+	0x8a, 0xd4, 0x88, 0x72, 0xe3, 0x82, 0xa0, 0x14, 0x09, 0xa9, 0x2a, 0x26, 0xb4, 0x5c, 0xad, 0x8d,
+	0xb3, 0x14, 0xab, 0x89, 0x77, 0xb1, 0x37, 0x11, 0xea, 0x91, 0x2b, 0x47, 0x1e, 0x8d, 0x13, 0x9c,
+	0x79, 0x10, 0x76, 0x67, 0xed, 0xc4, 0x8e, 0xe0, 0x36, 0xfb, 0x9b, 0xd9, 0x4f, 0xb3, 0xdf, 0xcc,
+	0x42, 0x77, 0x2e, 0xd3, 0x63, 0x99, 0x09, 0x25, 0xd0, 0x91, 0xa3, 0xfe, 0x83, 0x6b, 0x21, 0xae,
+	0x27, 0x7c, 0xc0, 0x64, 0x32, 0x60, 0x69, 0x2a, 0x14, 0x53, 0x89, 0x48, 0x73, 0x5b, 0x11, 0x20,
+	0x78, 0x1f, 0xc3, 0x8b, 0x0f, 0x1a, 0xce, 0xf2, 0x21, 0xff, 0x32, 0xe3, 0xb9, 0x0a, 0xbe, 0x3b,
+	0xb0, 0xa5, 0xe1, 0xdb, 0x34, 0x51, 0x05, 0xc2, 0x3e, 0x74, 0x3e, 0x8b, 0x5c, 0xa5, 0x6c, 0xca,
+	0xfd, 0xc6, 0xc3, 0xc6, 0x61, 0x77, 0xb8, 0x38, 0x23, 0x42, 0x4b, 0x8a, 0x4c, 0xf9, 0x0e, 0x71,
+	0x8a, 0xf1, 0x09, 0x00, 0xe9, 0x47, 0x32, 0xe3, 0x9f, 0xfc, 0xa6, 0xce, 0x6c, 0x9d, 0x6c, 0x1c,
+	0xcb, 0xd1, 0xb1, 0xd6, 0x0d, 0x4d, 0x62, 0xd8, 0xa5, 0x7c, 0xa8, 0xd3, 0x78, 0x0f, 0x3a, 0x89,
+	0x8c, 0x46, 0x13, 0x11, 0xdf, 0xf8, 0x2d, 0x12, 0x69, 0x27, 0xf2, 0x95, 0x39, 0xa2, 0x07, 0xcd,
+	0x71, 0x9a, 0xfb, 0x6b, 0x44, 0x4d, 0x88, 0x8f, 0xc1, 0xbb, 0xe1, 0x5c, 0xb2, 0x49, 0x32, 0xe7,
+	0x91, 0xe4, 0x59, 0x22, 0xc6, 0xbe, 0x4b, 0xe9, 0xed, 0x05, 0x0f, 0x09, 0xeb, 0x26, 0x76, 0x96,
+	0xa5, 0x2a, 0x99, 0x72, 0x31, 0x53, 0x7e, 0x9b, 0x6a, 0x97, 0x1a, 0x97, 0x96, 0xe3, 0x3e, 0xb4,
+	0x67, 0x39, 0x8f, 0x26, 0xb7, 0xc2, 0xef, 0xe8, 0x92, 0xce, 0xd0, 0xd5, 0xc7, 0xf3, 0x5b, 0x11,
+	0xbc, 0x20, 0x87, 0xae, 0xe4, 0x98, 0x29, 0x5e, 0xda, 0x51, 0xed, 0xb8, 0xf1, 0xcf, 0x8e, 0x9d,
+	0x45, 0xc7, 0xc1, 0x2e, 0xec, 0x68, 0x81, 0xa1, 0xbe, 0xc7, 0xb2, 0xd2, 0xd0, 0xe0, 0x97, 0x43,
+	0xb4, 0x34, 0x3e, 0x97, 0x7a, 0x24, 0x64, 0x65, 0xc5, 0x62, 0x8a, 0xf1, 0x11, 0x6c, 0xe6, 0xfa,
+	0x3d, 0x6c, 0x12, 0xa5, 0xb3, 0xe9, 0x88, 0x67, 0x85, 0xf4, 0x86, 0x85, 0x17, 0xc4, 0x6a, 0xf3,
+	0x69, 0xfe, 0x67, 0x3e, 0xad, 0xca, 0x7c, 0x34, 0x8b, 0xb9, 0x66, 0xd6, 0x58, 0x8a, 0x8d, 0x03,
+	0x31, 0x8b, 0x08, 0x5b, 0x43, 0xdd, 0x98, 0x9d, 0x9a, 0x84, 0x7e, 0x52, 0xca, 0x4b, 0xe7, 0x4c,
+	0x68, 0xae, 0x4f, 0x59, 0x7e, 0x43, 0x4e, 0xe9, 0xeb, 0x26, 0xc6, 0x03, 0x80, 0x38, 0xe3, 0xda,
+	0xa4, 0x71, 0xc4, 0x94, 0xdf, 0xa5, 0x4c, 0xb7, 0x20, 0x2f, 0x15, 0xf6, 0x60, 0x8d, 0x26, 0xee,
+	0x03, 0x65, 0xec, 0xa1, 0x74, 0x6b, 0x7d, 0x39, 0x5f, 0x2d, 0xc3, 0xbf, 0xca, 0x24, 0xe3, 0xb9,
+	0x91, 0xd9, 0xb0, 0x32, 0x05, 0xd1, 0x32, 0x01, 0x6c, 0xea, 0x26, 0x2b, 0x15, 0x9b, 0x54, 0xb1,
+	0x1e, 0xb3, 0xb3, 0xb2, 0x26, 0xd8, 0x81, 0xed, 0xc5, 0xfa, 0x5a, 0x63, 0x8b, 0x19, 0x94, 0x43,
+	0x2c, 0x60, 0x0f, 0xb0, 0x3a, 0x18, 0x4b, 0x8f, 0x0e, 0xa1, 0x53, 0x2e, 0x29, 0x02, 0xb8, 0x17,
+	0xef, 0xc2, 0xe1, 0xd9, 0x1b, 0xef, 0x0e, 0xb6, 0xa1, 0x79, 0xf5, 0x3a, 0xf4, 0x1a, 0x26, 0xb8,
+	0x3c, 0x0d, 0x3d, 0xe7, 0xe4, 0xb7, 0x03, 0x60, 0x66, 0xc8, 0xb3, 0x79, 0x12, 0x73, 0x7c, 0x0f,
+	0xae, 0x1d, 0x27, 0xf6, 0x8a, 0x4d, 0xaf, 0x7d, 0xab, 0xfe, 0xde, 0x0a, 0x2d, 0xba, 0xe8, 0x7f,
+	0xfb, 0xf9, 0xe7, 0x87, 0xd3, 0x43, 0xa4, 0x1f, 0x3a, 0x7f, 0x3a, 0xd0, 0xdf, 0x77, 0x90, 0x5b,
+	0xa1, 0x73, 0x68, 0x99, 0x67, 0x20, 0x16, 0x57, 0x2b, 0x5f, 0xb2, 0xbf, 0x5b, 0x63, 0x85, 0xd8,
+	0x7d, 0x12, 0xdb, 0x0b, 0xbc, 0xaa, 0x58, 0xa2, 0x2b, 0x9e, 0x37, 0x8e, 0xf0, 0x12, 0x5c, 0xeb,
+	0xc0, 0xa2, 0xc1, 0xda, 0x56, 0x2f, 0x1a, 0x5c, 0xb1, 0xe9, 0x80, 0x34, 0xf7, 0x83, 0x5a, 0x83,
+	0x33, 0xaa, 0x31, 0xaa, 0x57, 0xd0, 0x2e, 0x2c, 0xc4, 0x52, 0xa0, 0xbe, 0xeb, 0xfd, 0xbb, 0xab,
+	0x78, 0xa5, 0xd9, 0xdd, 0xaa, 0x70, 0x66, 0x8b, 0x46, 0x2e, 0x2d, 0xc8, 0xb3, 0xbf, 0x01, 0x00,
+	0x00, 0xff, 0xff, 0xba, 0x04, 0x57, 0xbd, 0xce, 0x04, 0x00, 0x00,
+}

+ 4 - 4
api/pb/vpn.pb.gw.go

@@ -202,13 +202,13 @@ func RegisterVPNServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 }
 
 var (
-	pattern_VPNService_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "status"}, ""))
+	pattern_VPNService_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "status"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_VPNService_Init_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "init"}, ""))
+	pattern_VPNService_Init_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "init"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_VPNService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "update"}, ""))
+	pattern_VPNService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "update"}, "", runtime.AssumeColonVerbOpt(true)))
 
-	pattern_VPNService_Restart_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "restart"}, ""))
+	pattern_VPNService_Restart_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "vpn", "restart"}, "", runtime.AssumeColonVerbOpt(true)))
 )
 
 var (

+ 7 - 3
api/rpc.go

@@ -101,6 +101,7 @@ func (s *UserService) List(ctx context.Context, req *pb.UserListRequest) (*pb.Us
 			BytesSent:          bytesSent,
 			BytesReceived:      bytesReceived,
 			ExpiresAt:          user.ExpiresAt().UTC().Format(time.RFC3339),
+			Description:        user.GetDescription(),
 		})
 	}
 
@@ -120,7 +121,7 @@ func (s *UserService) Create(ctx context.Context, req *pb.UserCreateRequest) (*p
 	}
 
 	var ut []*pb.UserResponse_User
-	user, err := ovpm.CreateNewUser(req.Username, req.Password, req.NoGw, req.HostId, req.IsAdmin)
+	user, err := ovpm.CreateNewUser(req.Username, req.Password, req.NoGw, req.HostId, req.IsAdmin, req.Description)
 	if err != nil {
 		return nil, err
 	}
@@ -131,6 +132,7 @@ func (s *UserService) Create(ctx context.Context, req *pb.UserCreateRequest) (*p
 		NoGw:               user.IsNoGW(),
 		HostId:             user.GetHostID(),
 		IsAdmin:            user.IsAdmin(),
+		Description:		user.GetDescription(),
 	}
 	ut = append(ut, &pbUser)
 
@@ -180,7 +182,7 @@ func (s *UserService) Update(ctx context.Context, req *pb.UserUpdateRequest) (*p
 
 	// User has admin perms?
 	if perms.Contains(ovpm.UpdateAnyUserPerm) {
-		err = user.Update(req.Password, noGW, req.HostId, admin)
+		err = user.Update(req.Password, noGW, req.HostId, admin, req.Description)
 		if err != nil {
 			return nil, err
 		}
@@ -190,6 +192,7 @@ func (s *UserService) Update(ctx context.Context, req *pb.UserUpdateRequest) (*p
 			NoGw:               user.IsNoGW(),
 			HostId:             user.GetHostID(),
 			IsAdmin:            user.IsAdmin(),
+			Description:        user.GetDescription(),
 		})
 		return &pb.UserResponse{Users: ut}, nil
 	}
@@ -200,7 +203,7 @@ func (s *UserService) Update(ctx context.Context, req *pb.UserUpdateRequest) (*p
 			return nil, grpc.Errorf(codes.PermissionDenied, "Caller can only update their user with ovpm.UpdateSelfPerm")
 		}
 
-		err = user.Update(req.Password, noGW, req.HostId, admin)
+		err = user.Update(req.Password, noGW, req.HostId, admin, req.Description)
 		if err != nil {
 			return nil, err
 		}
@@ -210,6 +213,7 @@ func (s *UserService) Update(ctx context.Context, req *pb.UserUpdateRequest) (*p
 			NoGw:               user.IsNoGW(),
 			HostId:             user.GetHostID(),
 			IsAdmin:            user.IsAdmin(),
+			Description:        user.GetDescription(),
 		})
 		return &pb.UserResponse{Users: ut}, nil
 	}

File diff suppressed because it is too large
+ 28 - 4
bindata/bindata.go


+ 48 - 62
go.mod

@@ -1,70 +1,56 @@
 module github.com/cad/ovpm
 
 require (
-	cloud.google.com/go v0.38.0 // indirect
-	github.com/PuerkitoBio/purell v1.1.0 // indirect
-	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
-	github.com/apache/thrift v0.12.0 // indirect
-	github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f
-	github.com/coreos/go-iptables v0.2.0
-	github.com/denisenkom/go-mssqldb v0.0.0-20190423183735-731ef375ac02 // indirect
-	github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e
-	github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
-	github.com/go-openapi/analysis v0.0.0-20180418034448-863ac7f90e00 // indirect
-	github.com/go-openapi/errors v0.0.0-20171226161601-7bcb96a367ba // indirect
-	github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa // indirect
-	github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d // indirect
-	github.com/go-openapi/loads v0.0.0-20171207192234-2a2b323bab96 // indirect
-	github.com/go-openapi/runtime v0.0.0-20180509184547-c0cae94704c7
-	github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee // indirect
-	github.com/go-openapi/strfmt v0.0.0-20180407011102-481808443b00 // indirect
-	github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9 // indirect
-	github.com/go-openapi/validate v0.0.0-20180502213133-9286f6d0e5c1 // indirect
-	github.com/go-sql-driver/mysql v1.4.1 // indirect
-	github.com/golang/mock v1.3.1 // indirect
-	github.com/golang/protobuf v1.3.1
-	github.com/google/btree v1.0.0 // indirect
-	github.com/google/go-cmp v0.3.0 // indirect
-	github.com/google/pprof v0.0.0-20190502144155-8358a9778bd1 // indirect
-	github.com/google/uuid v1.0.0
-	github.com/grpc-ecosystem/grpc-gateway v1.8.6
-	github.com/hashicorp/golang-lru v0.5.1 // indirect
-	github.com/jinzhu/gorm v1.9.1
-	github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
-	github.com/jinzhu/now v1.0.0 // indirect
+	cloud.google.com/go v0.41.0 // indirect
+	github.com/DataDog/zstd v1.4.0 // indirect
+	github.com/Shopify/sarama v1.23.0 // indirect
+	github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
+	github.com/coreos/go-iptables v0.4.1
+	github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 // indirect
+	github.com/dustin/go-humanize v1.0.0
+	github.com/eapache/go-resiliency v1.2.0 // indirect
+	github.com/go-kit/kit v0.9.0 // indirect
+	github.com/go-openapi/analysis v0.19.4 // indirect
+	github.com/go-openapi/runtime v0.19.3
+	github.com/go-openapi/strfmt v0.19.2 // indirect
+	github.com/go-openapi/swag v0.19.4 // indirect
+	github.com/gogo/protobuf v1.2.1 // indirect
+	github.com/golang/protobuf v1.3.2
+	github.com/google/uuid v1.1.1
+	github.com/gorilla/mux v1.7.3 // indirect
+	github.com/grpc-ecosystem/grpc-gateway v1.9.4
+	github.com/jcmturner/gofork v1.0.0 // indirect
+	github.com/jinzhu/gorm v1.9.10
 	github.com/jteeuwen/go-bindata v3.0.7+incompatible // indirect
-	github.com/kr/pty v1.1.4 // indirect
-	github.com/lib/pq v1.1.1 // indirect
-	github.com/mailru/easyjson v0.0.0-20180323154445-8b799c424f57 // indirect
-	github.com/mattn/go-runewidth v0.0.2 // indirect
-	github.com/mattn/go-sqlite3 v1.6.0 // indirect
-	github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 // indirect
-	github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84
-	github.com/openzipkin/zipkin-go v0.1.6 // indirect
-	github.com/pborman/uuid v1.2.0 // indirect
-	github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect
-	github.com/rogpeppe/fastuuid v1.1.0 // indirect
-	github.com/sirupsen/logrus v1.2.0
-	github.com/stretchr/testify v1.2.2
+	github.com/kisielk/errcheck v1.2.0 // indirect
+	github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
+	github.com/kr/pty v1.1.8 // indirect
+	github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
+	github.com/mattn/go-runewidth v0.0.4 // indirect
+	github.com/olekukonko/tablewriter v0.0.1
+	github.com/onsi/ginkgo v1.8.0 // indirect
+	github.com/onsi/gomega v1.5.0 // indirect
+	github.com/pkg/errors v0.8.1 // indirect
+	github.com/prometheus/common v0.6.0 // indirect
+	github.com/prometheus/procfs v0.0.3 // indirect
+	github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962 // indirect
+	github.com/rogpeppe/fastuuid v1.2.0 // indirect
+	github.com/sirupsen/logrus v1.4.2
+	github.com/stretchr/testify v1.3.0
 	github.com/urfave/cli v1.20.0
-	golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
-	golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522 // indirect
-	golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec // indirect
-	golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect
-	golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171 // indirect
-	golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5
-	golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a // indirect
-	golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 // indirect
-	golang.org/x/text v0.3.2 // indirect
-	golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
-	golang.org/x/tools v0.0.0-20190511041617-99f201b6807e // indirect
-	google.golang.org/api v0.5.0 // indirect
-	google.golang.org/appengine v1.5.0 // indirect
-	google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8
-	google.golang.org/grpc v1.20.1
+	go.mongodb.org/mongo-driver v1.0.4 // indirect
+	golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
+	golang.org/x/exp v0.0.0-20190627132806-fd42eb6b336f // indirect
+	golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9 // indirect
+	golang.org/x/mobile v0.0.0-20190607214518-6fa95d984e88 // indirect
+	golang.org/x/net v0.0.0-20190628185345-da137c7871d7
+	golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect
+	golang.org/x/tools v0.0.0-20190709194623-f82b303b69d7 // indirect
+	google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532
+	google.golang.org/grpc v1.22.0
 	gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect
 	gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect
-	gopkg.in/hlandau/passlib.v1 v1.0.9
-	gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528 // indirect
-	honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a // indirect
+	gopkg.in/hlandau/passlib.v1 v1.0.10
+	gopkg.in/jcmturner/gokrb5.v7 v7.3.0 // indirect
+	gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
 )

+ 172 - 0
go.sum

@@ -3,30 +3,49 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
 cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
 github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.23.0/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f h1:xHxhygLkJBQaXZ7H0JUpmqK/gfKO2DZXB7gAKT6bbBs=
 github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
+github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/coreos/go-iptables v0.2.0 h1:RmVRALeVCicZcF3rF05e0ooU9x9TmalN0HcT4hkhG5s=
 github.com/coreos/go-iptables v0.2.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-iptables v0.4.1 h1:TyEMaK2xD/EcB0385QcvX/OvI2XI7s4SJEI2EhZFfEU=
+github.com/coreos/go-iptables v0.4.1/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/denisenkom/go-mssqldb v0.0.0-20190423183735-731ef375ac02 h1:PS3xfVPa8N84AzoWZHFCbA0+ikz4f4skktfjQoNMsgk=
 github.com/denisenkom/go-mssqldb v0.0.0-20190423183735-731ef375ac02/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
+github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
+github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
+github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e h1:Fw7ZmgiklsLh5EQWyHh1sumKSCG1+yjEctIpGKib87s=
 github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
@@ -34,33 +53,72 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
+github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-openapi/analysis v0.0.0-20180418034448-863ac7f90e00 h1:b76E8vAKRC8E+tl1suDCKnc8Q50m2j/SW4PVR/uTlKU=
 github.com/go-openapi/analysis v0.0.0-20180418034448-863ac7f90e00/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
+github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
+github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
+github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
 github.com/go-openapi/errors v0.0.0-20171226161601-7bcb96a367ba h1:LiBJivCSkIa8fmEiRP/+qftG2ywqavn9M8H2bEOaeRU=
 github.com/go-openapi/errors v0.0.0-20171226161601-7bcb96a367ba/go.mod h1:La0D2x9HoXenv7MDEiAv6vWoe84CXFo0PQRk/jdQlww=
+github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
 github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa h1:hr8WVDjg4JKtQptZpzyb196TmruCs7PIsdJz8KAOZp8=
 github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
+github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
+github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d h1:k3UQ7Z8yFYq0BNkYykKIheY0HlZBl1Hku+pO9HE9FNU=
 github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 github.com/go-openapi/loads v0.0.0-20171207192234-2a2b323bab96 h1:ErY3tAaYwmcVoQJOJMnIXw+d4BRjD4Y0BnjOvNMlaEk=
 github.com/go-openapi/loads v0.0.0-20171207192234-2a2b323bab96/go.mod h1:5qFWh9T8iTbMizjsoC/EHEN3onRy+cfNRw/wV1iX1Og=
+github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
 github.com/go-openapi/runtime v0.0.0-20180509184547-c0cae94704c7 h1:9jmV0oJlCsVggDw9gDdSOt95n5lPzSstuuOv7erib2o=
 github.com/go-openapi/runtime v0.0.0-20180509184547-c0cae94704c7/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
+github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
+github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
+github.com/go-openapi/runtime v0.19.3/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
 github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee h1:eo0HQoNFtbiEc7+1gRF9pgW6azx8a1cO2fXcqq1MuD0=
 github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
 github.com/go-openapi/strfmt v0.0.0-20180407011102-481808443b00 h1:LpT8zb0lM93rm4LW+t7uLbXIrSzmIAtviiZKxM/Eqyc=
 github.com/go-openapi/strfmt v0.0.0-20180407011102-481808443b00/go.mod h1:/bCWipNKhC9QMhD8HRe2EGbU8G0D4Yvh0G6X4k1Xwvg=
+github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
+github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
 github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9 h1:+vsw187FKvA2QUGAcE+vQSfyxqLbUXixPYRRMAzwu04=
 github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
+github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
+github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.4/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/validate v0.0.0-20180502213133-9286f6d0e5c1 h1:ObcdPnoHxgJsYeNxoKGnxm6odWwez3ac671GgTJ0i/w=
 github.com/go-openapi/validate v0.0.0-20180502213133-9286f6d0e5c1/go.mod h1:ve8xoSHgqBUifiKgaVbxLmOE0ckvH0oXfsJcnm6SIz0=
+github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
+github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
 github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -70,7 +128,9 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
@@ -79,92 +139,157 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/pprof v0.0.0-20190502144155-8358a9778bd1/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/grpc-ecosystem/grpc-gateway v1.3.1 h1:k2neygAEBYavP90THffKBVlkASdxu4XiI8cAWuL3MG0=
 github.com/grpc-ecosystem/grpc-gateway v1.3.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
 github.com/grpc-ecosystem/grpc-gateway v1.8.6 h1:XvND7+MPP7Jp+JpqSZ7naSl5nVZf6k0LbL1V3EKh0zc=
 github.com/grpc-ecosystem/grpc-gateway v1.8.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
 github.com/jinzhu/gorm v1.9.1 h1:lDSDtsCt5AGGSKTs8AHlSDbbgif4G4+CKJ8ETBDVHTA=
 github.com/jinzhu/gorm v1.9.1/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
+github.com/jinzhu/gorm v1.9.10 h1:HvrsqdhCW78xpJF67g1hMxS6eCToo9PZH4LDB8WKPac=
+github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY=
 github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYXJi4pg1ZKM7nxc5AfXfojeLLW7O5J3k=
 github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.0.0 h1:6WV8LvwPpDhKjo5U9O6b4+xdG/jTXNPwlDme/MTo8Ns=
 github.com/jinzhu/now v1.0.0/go.mod h1:oHTiXerJ20+SfYcrdlBO7rzZRJWGwSTQ0iUY2jI6Gfc=
+github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=
 github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
+github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
 github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/mailru/easyjson v0.0.0-20180323154445-8b799c424f57 h1:qhv1ir3dIyOFmFU+5KqG4dF3zSQTA4nn1DFhu2NQC44=
 github.com/mailru/easyjson v0.0.0-20180323154445-8b799c424f57/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-sqlite3 v1.6.0 h1:TDwTWbeII+88Qy55nWlof0DclgAtI4LqGujkYMzmQII=
 github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
+github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 h1:/rdJjIiKG5rRdwG5yxHmSE/7ZREjpyC0kL7GxGT/qJw=
 github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
 github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
+go.mongodb.org/mongo-driver v1.0.4/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190627132806-fd42eb6b336f/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -172,9 +297,11 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
 golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mobile v0.0.0-20190607214518-6fa95d984e88/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -182,12 +309,20 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
 golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -203,9 +338,19 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
 golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
@@ -214,34 +359,51 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190511041617-99f201b6807e/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190709194623-f82b303b69d7/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
 google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
 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.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo=
 google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8 h1:x913Lq/RebkvUmRSdQ8MNb0GZKn+SR1ESfoetcQSeak=
 google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
 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.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -254,8 +416,16 @@ gopkg.in/hlandau/measurable.v1 v1.0.1 h1:wH5UZKCRUnRr1iD+xIZfwhtxhmr+bprRJttqA1R
 gopkg.in/hlandau/measurable.v1 v1.0.1/go.mod h1:6N+SYJGMTmetsx7wskULP+juuO+++tsHJkAgzvzsbuM=
 gopkg.in/hlandau/passlib.v1 v1.0.9 h1:VfsIu2uKK6xsr9VHCtJtIgNuZ/RNUrIi67hxl8K/7Gg=
 gopkg.in/hlandau/passlib.v1 v1.0.9/go.mod h1:wxGAv2CtQHlzWY8NJp+p045yl4WHyX7v2T6XbOcmqjM=
+gopkg.in/hlandau/passlib.v1 v1.0.10 h1:q5xh9ZHp907XTjVw8/EqG03//fnlITnIYQmv4Gn7TpE=
+gopkg.in/hlandau/passlib.v1 v1.0.10/go.mod h1:wxGAv2CtQHlzWY8NJp+p045yl4WHyX7v2T6XbOcmqjM=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
 gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528 h1:/saqWwm73dLmuzbNhe92F0QsZ/KiFND+esHco2v1hiY=
 gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -267,3 +437,5 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

+ 3 - 3
net_test.go

@@ -207,7 +207,7 @@ func TestNetAssociate(t *testing.T) {
 	cidrStr := "192.168.1.0/24"
 	netType := SERVERNET
 	userName := "testUser2"
-	user, err := CreateNewUser(userName, "123", false, 0, true)
+	user, err := CreateNewUser(userName, "123", false, 0, true, "description")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -255,7 +255,7 @@ func TestNetDissociate(t *testing.T) {
 	cidrStr := "192.168.1.0/24"
 	netType := SERVERNET
 	userName := "testUser2"
-	user, err := CreateNewUser(userName, "123", false, 0, true)
+	user, err := CreateNewUser(userName, "123", false, 0, true, "description")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -305,7 +305,7 @@ func TestNetGetAssociatedUsers(t *testing.T) {
 	cidrStr := "192.168.1.0/24"
 	netType := SERVERNET
 	userName := "testUser2"
-	user, _ := CreateNewUser(userName, "123", false, 0, true)
+	user, _ := CreateNewUser(userName, "123", false, 0, true, "description")
 
 	n, _ := CreateNewNetwork(netName, cidrStr, netType, "")
 	n.Associate(user.Username)

+ 3 - 0
template/auth.swagger.json

@@ -106,6 +106,9 @@
         },
         "expires_at": {
           "type": "string"
+        },
+        "description": {
+          "type": "string"
         }
       }
     },

File diff suppressed because it is too large
+ 0 - 0
template/bundle.js


+ 9 - 0
template/user.swagger.json

@@ -210,6 +210,9 @@
         },
         "expires_at": {
           "type": "string"
+        },
+        "description": {
+          "type": "string"
         }
       }
     },
@@ -260,6 +263,9 @@
         "is_admin": {
           "type": "boolean",
           "format": "boolean"
+        },
+        "description": {
+          "type": "string"
         }
       }
     },
@@ -327,6 +333,9 @@
         },
         "admin_pref": {
           "$ref": "#/definitions/UserUpdateRequestAdminPref"
+        },
+        "description": {
+          "type": "string"
         }
       }
     }

+ 9 - 2
user.go

@@ -35,6 +35,7 @@ type dbUserModel struct {
 	HostID             uint32 // not user writable
 	Admin              bool
 	AuthToken          string // auth token
+	Description        string
 }
 
 // User represents a vpn user.
@@ -128,7 +129,7 @@ func GetAllUsers() ([]*User, error) {
 //
 // It also generates the necessary client keys and signs certificates with the current
 // server's CA.
-func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bool) (*User, error) {
+func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bool, description string) (*User, error) {
 	svr := TheServer()
 	if !svr.IsInitialized() {
 		return nil, fmt.Errorf("you first need to create server")
@@ -191,6 +192,7 @@ func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bo
 		NoGW:               nogw,
 		HostID:             hostid,
 		Admin:              admin,
+		Description:		description,
 	}
 	user.setPassword(password)
 
@@ -211,7 +213,7 @@ func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bo
 // Update updates the user's attributes and writes them to the database.
 //
 // How this method works is similiar to PUT semantics of REST. It sets the user record fields to the provided function arguments.
-func (u *User) Update(password string, nogw bool, hostid uint32, admin bool) error {
+func (u *User) Update(password string, nogw bool, hostid uint32, admin bool, description string) error {
 	svr := TheServer()
 	if !svr.IsInitialized() {
 		return fmt.Errorf("you first need to create server")
@@ -225,6 +227,7 @@ func (u *User) Update(password string, nogw bool, hostid uint32, admin bool) err
 	u.NoGW = nogw
 	u.HostID = hostid
 	u.Admin = admin
+	u.Description = description
 
 	if hostid != 0 {
 		ip := HostID2IP(hostid)
@@ -415,6 +418,10 @@ func (u *User) getKey() string {
 	return u.Key
 }
 
+func (u *User) GetDescription() string {
+	return u.Description
+}
+
 // ConnectionStatus returns information about user's connection to the VPN server.
 func (u *User) ConnectionStatus() (isConnected bool, connectedSince time.Time, bytesSent uint64, bytesReceived uint64) {
 	var found *clEntry

+ 1 - 1
user_internal_test.go

@@ -19,7 +19,7 @@ func TestUser_ConnectionStatus(t *testing.T) {
 	svr.openFunc = func(path string) (io.Reader, error) {
 		return nil, nil
 	}
-	usr1, err := CreateNewUser("usr1", "1234", true, 0, false)
+	usr1, err := CreateNewUser("usr1", "1234", true, 0, false, "description")
 	if err != nil {
 		t.Fatalf("user creation failed: %v", err)
 	}

+ 14 - 14
user_test.go

@@ -25,7 +25,7 @@ func TestCreateNewUser(t *testing.T) {
 	noGW := false
 
 	// Test:
-	user, err := ovpm.CreateNewUser(username, password, noGW, 0, true)
+	user, err := ovpm.CreateNewUser(username, password, noGW, 0, true, "description")
 	if err != nil {
 		t.Fatalf("user can not be created: %v", err)
 	}
@@ -66,7 +66,7 @@ func TestCreateNewUser(t *testing.T) {
 
 	// Is NoGW attr working properly?
 	noGW = true
-	user, err = ovpm.CreateNewUser(username, password, noGW, 0, true)
+	user, err = ovpm.CreateNewUser(username, password, noGW, 0, true, "description")
 	if err != nil {
 		t.Fatalf("user can not be created: %v", err)
 	}
@@ -76,7 +76,7 @@ func TestCreateNewUser(t *testing.T) {
 
 	// Try to create a user with an invalid static ip.
 	user = nil
-	_, err = ovpm.CreateNewUser("staticuser", password, noGW, ovpm.IP2HostID(net.ParseIP("8.8.8.8").To4()), true)
+	_, err = ovpm.CreateNewUser("staticuser", password, noGW, ovpm.IP2HostID(net.ParseIP("8.8.8.8").To4()), true, "description")
 	if err == nil {
 		t.Fatalf("user creation expected to err but it didn't")
 	}
@@ -95,7 +95,7 @@ func TestCreateNewUser(t *testing.T) {
 	}
 
 	for _, tt := range usernametests {
-		_, err := ovpm.CreateNewUser(tt.username, "1234", false, 0, true)
+		_, err := ovpm.CreateNewUser(tt.username, "1234", false, 0, true, "description")
 		if ok := (err == nil); ok != tt.ok {
 			t.Fatalf("expcted condition failed '%s': %v", tt.username, err)
 		}
@@ -114,7 +114,7 @@ func TestUserUpdate(t *testing.T) {
 	noGW := false
 
 	// Test:
-	user, err := ovpm.CreateNewUser(username, password, noGW, 0, true)
+	user, err := ovpm.CreateNewUser(username, password, noGW, 0, true, "description")
 	if err != nil {
 		t.Fatalf("user can not be created: %v", err)
 	}
@@ -135,7 +135,7 @@ func TestUserUpdate(t *testing.T) {
 	}
 
 	for _, tt := range updatetests {
-		err := user.Update(tt.password, tt.noGW, tt.hostid, true)
+		err := user.Update(tt.password, tt.noGW, tt.hostid, true, "description")
 		if (err == nil) != tt.ok {
 			t.Errorf("user is expected to be able to update but it gave us this error instead: %v", err)
 		}
@@ -150,7 +150,7 @@ func TestUserPasswordCorrect(t *testing.T) {
 
 	// Prepare:
 	initialPassword := "g00dp@ssW0rd9"
-	user, _ := ovpm.CreateNewUser("testUser", initialPassword, false, 0, true)
+	user, _ := ovpm.CreateNewUser("testUser", initialPassword, false, 0, true, "description")
 
 	// Test:
 	// Is user created with the correct password?
@@ -167,7 +167,7 @@ func TestUserPasswordReset(t *testing.T) {
 
 	// Prepare:
 	initialPassword := "g00dp@ssW0rd9"
-	user, _ := ovpm.CreateNewUser("testUser", initialPassword, false, 0, true)
+	user, _ := ovpm.CreateNewUser("testUser", initialPassword, false, 0, true, "description")
 
 	// Test:
 
@@ -194,7 +194,7 @@ func TestUserDelete(t *testing.T) {
 
 	// Prepare:
 	username := "testUser"
-	user, _ := ovpm.CreateNewUser(username, "1234", false, 0, true)
+	user, _ := ovpm.CreateNewUser(username, "1234", false, 0, true, "description")
 
 	// Test:
 
@@ -232,7 +232,7 @@ func TestUserGet(t *testing.T) {
 
 	// Prepare:
 	username := "testUser"
-	user, _ := ovpm.CreateNewUser(username, "1234", false, 0, true)
+	user, _ := ovpm.CreateNewUser(username, "1234", false, 0, true, "description")
 
 	// Test:
 	// Is user fetchable?
@@ -260,7 +260,7 @@ func TestUserGetAll(t *testing.T) {
 	for i := 0; i < count; i++ {
 		username := fmt.Sprintf("user%d", i)
 		password := fmt.Sprintf("password%d", i)
-		user, _ := ovpm.CreateNewUser(username, password, false, 0, true)
+		user, _ := ovpm.CreateNewUser(username, password, false, 0, true, "description")
 		users = append(users, user)
 	}
 
@@ -294,7 +294,7 @@ func TestUserRenew(t *testing.T) {
 	svr.Init("localhost", "", ovpm.UDPProto, "", "", "", "", false)
 
 	// Prepare:
-	user, _ := ovpm.CreateNewUser("user", "1234", false, 0, true)
+	user, _ := ovpm.CreateNewUser("user", "1234", false, 0, true, "description")
 
 	// Test:
 	// Re initialize the server.
@@ -335,7 +335,7 @@ func TestUserIPAllocator(t *testing.T) {
 		{"user6", true, ovpm.IP2HostID(net.ParseIP("10.9.0.1").To4()), "10.9.0.7/24", false},
 	}
 	for _, tt := range iptests {
-		user, err := ovpm.CreateNewUser(tt.username, "pass", tt.gw, tt.hostid, true)
+		user, err := ovpm.CreateNewUser(tt.username, "pass", tt.gw, tt.hostid, true, "description")
 		if (err == nil) == !tt.pass {
 			t.Fatalf("expected pass %t %s", tt.pass, err)
 		}
@@ -354,7 +354,7 @@ func TestUser_ExpiresAt(t *testing.T) {
 	svr.Init("localhost", "", ovpm.UDPProto, "", "", "", "", false)
 
 	// Test:
-	u1, err := ovpm.CreateNewUser("test", "1234", true, 0, false)
+	u1, err := ovpm.CreateNewUser("test", "1234", true, 0, false, "description")
 	if err != nil {
 		t.Fatalf("test preperation failed: %v", err)
 	}

+ 6 - 6
vpn_test.go

@@ -65,7 +65,7 @@ func TestVPNDeinit(t *testing.T) {
 	// Prepare:
 	// Initialize the server.
 	TheServer().Init("localhost", "", UDPProto, "", "", "", "", false)
-	u, err := CreateNewUser("user", "p", false, 0, true)
+	u, err := CreateNewUser("user", "p", false, 0, true, "description")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -206,7 +206,7 @@ func TestVPNDumpsClientConfig(t *testing.T) {
 	svr.Init("localhost", "", UDPProto, "", "", "", "", false)
 
 	// Prepare:
-	user, _ := CreateNewUser("user", "password", false, 0, true)
+	user, _ := CreateNewUser("user", "password", false, 0, true, "description")
 
 	// Test:
 	clientConfigBlob, err := svr.DumpsClientConfig(user.GetUsername())
@@ -230,7 +230,7 @@ func TestVPNDumpClientConfig(t *testing.T) {
 
 	// Prepare:
 	noGW := false
-	user, err := CreateNewUser("user", "password", noGW, 0, true)
+	user, err := CreateNewUser("user", "password", noGW, 0, true, "description")
 	if err != nil {
 		t.Fatalf("can not create user: %v", err)
 	}
@@ -257,7 +257,7 @@ func TestVPNDumpClientConfig(t *testing.T) {
 	user.Delete()
 
 	noGW = true
-	user, err = CreateNewUser("user", "password", noGW, 0, true)
+	user, err = CreateNewUser("user", "password", noGW, 0, true, "description")
 	if err != nil {
 		t.Fatalf("can not create user: %v", err)
 	}
@@ -483,11 +483,11 @@ func TestGetConnectedUsers(t *testing.T) {
 		return nil, nil
 	}
 	// Create the corresponding users for test.
-	usr1, err := CreateNewUser("usr1", "1234", true, 0, false)
+	usr1, err := CreateNewUser("usr1", "1234", true, 0, false, "description")
 	if err != nil {
 		t.Fatalf("user creation failed: %v", err)
 	}
-	usr2, err := CreateNewUser("usr2", "1234", true, 0, false)
+	usr2, err := CreateNewUser("usr2", "1234", true, 0, false, "description")
 	if err != nil {
 		t.Fatalf("user creation failed: %v", err)
 	}

+ 9 - 1
webui/ovpm/app/components/Dashboard/AdminDashboard/UserEdit/index.jsx

@@ -6,6 +6,8 @@ import Input from 'muicss/lib/react/input';
 import Option from 'muicss/lib/react/option';
 import Select from 'muicss/lib/react/select';
 import Checkbox from 'muicss/lib/react/checkbox';
+import Textarea from 'muicss/lib/react/textarea';
+
 
 
 export default class UserEdit extends React.Component {
@@ -19,6 +21,7 @@ export default class UserEdit extends React.Component {
             ipAllocationMethod: this.props.ipAllocationMethod ? this.props.ipAllocationMethod : "dynamic",
             pushGW: this.props.pushGW != undefined ? this.props.pushGW : true,
             isAdmin: this.props.isAdmin ? this.props.isAdmin : false,
+            description: this.props.description ? this.props.description : "",
         }
 
     }
@@ -33,6 +36,9 @@ export default class UserEdit extends React.Component {
     handlePasswordChange(e) {
         this.setState({password: e.target.value})
     }
+    handleDescriptionChange(e) {
+        this.setState({description: e.target.value})
+    }
 
     handleStaticIPChange(e) {
         this.setState({staticIP: e.target.value})
@@ -77,7 +83,9 @@ export default class UserEdit extends React.Component {
                 {staticIPInput}
                 <Checkbox label="Push GW" checked={this.state.pushGW} onChange={this.handlePushGWChange.bind(this)}/>
                 <Checkbox label="Make Admin" checked={this.state.isAdmin} onChange={this.handleIsAdminChange.bind(this)}/>
-                <div className="mui--pull-right">
+                <Textarea placeholder="User description" value={this.state.description} onChange={this.handleDescriptionChange.bind(this)} cols={50} rows={5} />
+
+                    <div className="mui--pull-right">
                     <Button color="primary" onClick={this.handleFormSubmit.bind(this)} required={true}>Save</Button>
                     <Button color="danger" onClick={this.handleFormCancel.bind(this)} required={true}>Cancel</Button>
                 </div>

+ 5 - 1
webui/ovpm/app/components/Dashboard/AdminDashboard/index.jsx

@@ -199,6 +199,7 @@ export default class AdminDashboard extends React.Component {
             no_gw: user.pushGW,
             host_id: 0, // handle this host_id problem
             is_admin: user.isAdmin,
+            description: user.description,
         }
         userObj.no_gw = !user.pushGW
         userObj.admin_pref = user.isAdmin ? "ADMIN" : "NOADMIN"
@@ -229,6 +230,7 @@ export default class AdminDashboard extends React.Component {
             admin_pref: "NOPREFADMIN",
             static_pref: "NOPREFSTATIC",
             hostid: 0,
+            description: user.description,
         }
 
         if (user.password !== "") {
@@ -466,6 +468,7 @@ export default class AdminDashboard extends React.Component {
                 <tr key={"user" + i}>
                     <td>{i + 1}</td>
                     <td>{isOnline} {this.state.users[i].username} {isAdmin}</td>
+                    <td style={{"white-space": "pre-line"}}>{this.state.users[i].description}</td>
                     <td>{this.state.users[i].ip_net} {isStatic}</td>
                     <td>{createdAt}</td>
                     <td>{certExpiry}</td>
@@ -515,7 +518,7 @@ export default class AdminDashboard extends React.Component {
                             <UserEdit title="Create New User" onCancel={this.handleCloseModal.bind(this)} onSave={this.handleNewUserSave.bind(this)} isUsernameDisabled={false} />
                         </Modal>
                         <Modal isOpen={this.state.modal === EDITINGUSER} contentLabel="Modal" style={modalStyle}>
-                            <UserEdit title="Update User" onCancel={this.handleCloseModal.bind(this)} onSave={this.handleUpdateUserSave.bind(this)} isUsernameDisabled={true} username={this.state.editedUser.username} isAdmin={this.state.editedUser.is_admin} pushGW={(!this.state.editedUser.no_gw)} ipAllocationMethod={this.state.editedUser.host_id == 0 ? "dynamic" : "static"} staticIP={this.state.editedUser.host_id == 0 ? "" : num2dot(this.state.editedUser.host_id)} />
+                            <UserEdit title="Update User" onCancel={this.handleCloseModal.bind(this)} onSave={this.handleUpdateUserSave.bind(this)} isUsernameDisabled={true} username={this.state.editedUser.username} isAdmin={this.state.editedUser.is_admin} pushGW={(!this.state.editedUser.no_gw)} ipAllocationMethod={this.state.editedUser.host_id == 0 ? "dynamic" : "static"} staticIP={this.state.editedUser.host_id == 0 ? "" : num2dot(this.state.editedUser.host_id)} description={this.state.editedUser.description} />
                         </Modal>
                         <Modal isOpen={this.state.modal === DEFININGNEWNETWORK} contentLabel="Modal" style={modalStyle}>
                             <NetworkEdit title="New Network" onCancel={this.handleCloseModal.bind(this)} onSave={this.handleDefineNetworkSave.bind(this)} />
@@ -538,6 +541,7 @@ export default class AdminDashboard extends React.Component {
                                             <tr>
                                                 <th></th>
                                                 <th>USERNAME</th>
+                                                <th>DESCRIPTION</th>
                                                 <th>IP</th>
                                                 <th>CREATED AT</th>
                                                 <th>CERT</th>

File diff suppressed because it is too large
+ 0 - 0
webui/ovpm/public/bundle.js


Some files were not shown because too many files changed in this diff