diff --git a/proto/message.proto b/proto/message.proto index 4688275..f519c0b 100644 --- a/proto/message.proto +++ b/proto/message.proto @@ -1,10 +1,11 @@ syntax = "proto3"; -option go_package = "./"; - package message; +option go_package = "git.madsky.ru/lotti/message/pkg/messages/message"; + import "google/protobuf/empty.proto"; +import "validate/validate.proto"; service MessageService { @@ -29,8 +30,8 @@ service MessageService { // User message CreateUserRequest { - string email = 1; - string name = 2; + string email = 1 [(validate.rules).string.email = true]; + optional string name = 2; } message CreateUserResponse { @@ -38,8 +39,8 @@ message CreateUserResponse { } message UpdateUserRequest { - int32 id = 1; - optional string token = 2; + int32 id = 1 [(validate.rules).int32.gt = 0]; + optional string token = 2; // todo optional string description = 3; } @@ -48,11 +49,11 @@ message UpdateUserResponse { } message GetUserByTokenRequest { - string token = 1; + string token = 1; // todo } message GetUserByEmailRequest { - string email = 1; + string email = 1 [(validate.rules).string.email = true]; } message GetUserResponse { @@ -82,6 +83,7 @@ message UserForChatResponse { string email = 3; optional string description = 4; optional bool is_admin = 5; + optional string name = 6; } // User end @@ -102,7 +104,11 @@ message CreateChatResponse { } message UpdateChatRequest { - string id = 1; + string id = 1 [(validate.rules).string = { + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + min_len: 36, + max_len: 36 + }]; repeated UserForChat users = 2; } @@ -120,7 +126,7 @@ message GetChatResponse { message ListChatRequest { int32 page = 1; - int32 user_id = 2; + int32 user_id = 2 [(validate.rules).int32.gt = 0]; } message ListChatResponse { @@ -137,8 +143,12 @@ message Chat { // Message message CreateMessageRequest { - string chat_id = 2; - int32 user_id = 3; + string chat_id = 2 [(validate.rules).string = { + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + min_len: 36, + max_len: 36 + }]; + int32 user_id = 3 [(validate.rules).int32.gt = 0]; optional string text = 4; optional string image = 5; optional string video = 6; @@ -150,8 +160,12 @@ message CreateMessageResponse { } message UpdateMessageRequest { - int32 id = 1; - string chat_id = 2; + int32 id = 1 [(validate.rules).int32.gt = 0]; + string chat_id = 2 [(validate.rules).string = { + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + min_len: 36, + max_len: 36 + }]; optional string text = 3; optional string image = 4; optional string video = 5; @@ -163,7 +177,7 @@ message UpdateMessageResponse { } message GetMessageRequest { - int32 id = 1; + int32 id = 1 [(validate.rules).int32.gt = 0]; } message GetMessageResponse { @@ -172,7 +186,11 @@ message GetMessageResponse { message ListMessageRequest { int32 page = 1; - string chat_id = 2; + string chat_id = 2 [(validate.rules).string = { + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + min_len: 36, + max_len: 36 + }]; } message ListMessageResponse { diff --git a/proto/validate/validate.proto b/proto/validate/validate.proto new file mode 100644 index 0000000..5aa9653 --- /dev/null +++ b/proto/validate/validate.proto @@ -0,0 +1,862 @@ +syntax = "proto2"; +package validate; + +option go_package = "github.com/envoyproxy/protoc-gen-validate/validate"; +option java_package = "io.envoyproxy.pgv.validate"; + +import "google/protobuf/descriptor.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// Validation rules applied at the message level +extend google.protobuf.MessageOptions { + // Disabled nullifies any validation rules for this message, including any + // message fields associated with it that do support validation. + optional bool disabled = 1071; + // Ignore skips generation of validation methods for this message. + optional bool ignored = 1072; +} + +// Validation rules applied at the oneof level +extend google.protobuf.OneofOptions { + // Required ensures that exactly one the field options in a oneof is set; + // validation fails if no fields in the oneof are set. + optional bool required = 1071; +} + +// Validation rules applied at the field level +extend google.protobuf.FieldOptions { + // Rules specify the validations to be performed on this field. By default, + // no validation is performed against a field. + optional FieldRules rules = 1071; +} + +// FieldRules encapsulates the rules for each type of field. Depending on the +// field, the correct set should be used to ensure proper validations. +message FieldRules { + optional MessageRules message = 17; + oneof type { + // Scalar Field Types + FloatRules float = 1; + DoubleRules double = 2; + Int32Rules int32 = 3; + Int64Rules int64 = 4; + UInt32Rules uint32 = 5; + UInt64Rules uint64 = 6; + SInt32Rules sint32 = 7; + SInt64Rules sint64 = 8; + Fixed32Rules fixed32 = 9; + Fixed64Rules fixed64 = 10; + SFixed32Rules sfixed32 = 11; + SFixed64Rules sfixed64 = 12; + BoolRules bool = 13; + StringRules string = 14; + BytesRules bytes = 15; + + // Complex Field Types + EnumRules enum = 16; + RepeatedRules repeated = 18; + MapRules map = 19; + + // Well-Known Field Types + AnyRules any = 20; + DurationRules duration = 21; + TimestampRules timestamp = 22; + } +} + +// FloatRules describes the constraints applied to `float` values +message FloatRules { + // Const specifies that this field must be exactly the specified value + optional float const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional float lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional float lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional float gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional float gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated float in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated float not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// DoubleRules describes the constraints applied to `double` values +message DoubleRules { + // Const specifies that this field must be exactly the specified value + optional double const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional double lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional double lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional double gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional double gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated double in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated double not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// Int32Rules describes the constraints applied to `int32` values +message Int32Rules { + // Const specifies that this field must be exactly the specified value + optional int32 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional int32 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional int32 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional int32 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional int32 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated int32 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated int32 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// Int64Rules describes the constraints applied to `int64` values +message Int64Rules { + // Const specifies that this field must be exactly the specified value + optional int64 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional int64 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional int64 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional int64 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional int64 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated int64 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated int64 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// UInt32Rules describes the constraints applied to `uint32` values +message UInt32Rules { + // Const specifies that this field must be exactly the specified value + optional uint32 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional uint32 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional uint32 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional uint32 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional uint32 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated uint32 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated uint32 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// UInt64Rules describes the constraints applied to `uint64` values +message UInt64Rules { + // Const specifies that this field must be exactly the specified value + optional uint64 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional uint64 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional uint64 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional uint64 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional uint64 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated uint64 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated uint64 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// SInt32Rules describes the constraints applied to `sint32` values +message SInt32Rules { + // Const specifies that this field must be exactly the specified value + optional sint32 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional sint32 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional sint32 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional sint32 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional sint32 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated sint32 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated sint32 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// SInt64Rules describes the constraints applied to `sint64` values +message SInt64Rules { + // Const specifies that this field must be exactly the specified value + optional sint64 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional sint64 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional sint64 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional sint64 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional sint64 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated sint64 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated sint64 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// Fixed32Rules describes the constraints applied to `fixed32` values +message Fixed32Rules { + // Const specifies that this field must be exactly the specified value + optional fixed32 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional fixed32 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional fixed32 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional fixed32 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional fixed32 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated fixed32 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated fixed32 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// Fixed64Rules describes the constraints applied to `fixed64` values +message Fixed64Rules { + // Const specifies that this field must be exactly the specified value + optional fixed64 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional fixed64 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional fixed64 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional fixed64 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional fixed64 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated fixed64 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated fixed64 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// SFixed32Rules describes the constraints applied to `sfixed32` values +message SFixed32Rules { + // Const specifies that this field must be exactly the specified value + optional sfixed32 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional sfixed32 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional sfixed32 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional sfixed32 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional sfixed32 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated sfixed32 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated sfixed32 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// SFixed64Rules describes the constraints applied to `sfixed64` values +message SFixed64Rules { + // Const specifies that this field must be exactly the specified value + optional sfixed64 const = 1; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional sfixed64 lt = 2; + + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + optional sfixed64 lte = 3; + + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + optional sfixed64 gt = 4; + + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + optional sfixed64 gte = 5; + + // In specifies that this field must be equal to one of the specified + // values + repeated sfixed64 in = 6; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated sfixed64 not_in = 7; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 8; +} + +// BoolRules describes the constraints applied to `bool` values +message BoolRules { + // Const specifies that this field must be exactly the specified value + optional bool const = 1; +} + +// StringRules describe the constraints applied to `string` values +message StringRules { + // Const specifies that this field must be exactly the specified value + optional string const = 1; + + // Len specifies that this field must be the specified number of + // characters (Unicode code points). Note that the number of + // characters may differ from the number of bytes in the string. + optional uint64 len = 19; + + // MinLen specifies that this field must be the specified number of + // characters (Unicode code points) at a minimum. Note that the number of + // characters may differ from the number of bytes in the string. + optional uint64 min_len = 2; + + // MaxLen specifies that this field must be the specified number of + // characters (Unicode code points) at a maximum. Note that the number of + // characters may differ from the number of bytes in the string. + optional uint64 max_len = 3; + + // LenBytes specifies that this field must be the specified number of bytes + optional uint64 len_bytes = 20; + + // MinBytes specifies that this field must be the specified number of bytes + // at a minimum + optional uint64 min_bytes = 4; + + // MaxBytes specifies that this field must be the specified number of bytes + // at a maximum + optional uint64 max_bytes = 5; + + // Pattern specifies that this field must match against the specified + // regular expression (RE2 syntax). The included expression should elide + // any delimiters. + optional string pattern = 6; + + // Prefix specifies that this field must have the specified substring at + // the beginning of the string. + optional string prefix = 7; + + // Suffix specifies that this field must have the specified substring at + // the end of the string. + optional string suffix = 8; + + // Contains specifies that this field must have the specified substring + // anywhere in the string. + optional string contains = 9; + + // NotContains specifies that this field cannot have the specified substring + // anywhere in the string. + optional string not_contains = 23; + + // In specifies that this field must be equal to one of the specified + // values + repeated string in = 10; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated string not_in = 11; + + // WellKnown rules provide advanced constraints against common string + // patterns + oneof well_known { + // Email specifies that the field must be a valid email address as + // defined by RFC 5322 + bool email = 12; + + // Hostname specifies that the field must be a valid hostname as + // defined by RFC 1034. This constraint does not support + // internationalized domain names (IDNs). + bool hostname = 13; + + // Ip specifies that the field must be a valid IP (v4 or v6) address. + // Valid IPv6 addresses should not include surrounding square brackets. + bool ip = 14; + + // Ipv4 specifies that the field must be a valid IPv4 address. + bool ipv4 = 15; + + // Ipv6 specifies that the field must be a valid IPv6 address. Valid + // IPv6 addresses should not include surrounding square brackets. + bool ipv6 = 16; + + // Uri specifies that the field must be a valid, absolute URI as defined + // by RFC 3986 + bool uri = 17; + + // UriRef specifies that the field must be a valid URI as defined by RFC + // 3986 and may be relative or absolute. + bool uri_ref = 18; + + // Address specifies that the field must be either a valid hostname as + // defined by RFC 1034 (which does not support internationalized domain + // names or IDNs), or it can be a valid IP (v4 or v6). + bool address = 21; + + // Uuid specifies that the field must be a valid UUID as defined by + // RFC 4122 + bool uuid = 22; + + // WellKnownRegex specifies a common well known pattern defined as a regex. + KnownRegex well_known_regex = 24; + } + + // This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable + // strict header validation. + // By default, this is true, and HTTP header validations are RFC-compliant. + // Setting to false will enable a looser validations that only disallows + // \r\n\0 characters, which can be used to bypass header matching rules. + optional bool strict = 25 [default = true]; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 26; +} + +// WellKnownRegex contain some well-known patterns. +enum KnownRegex { + UNKNOWN = 0; + + // HTTP header name as defined by RFC 7230. + HTTP_HEADER_NAME = 1; + + // HTTP header value as defined by RFC 7230. + HTTP_HEADER_VALUE = 2; +} + +// BytesRules describe the constraints applied to `bytes` values +message BytesRules { + // Const specifies that this field must be exactly the specified value + optional bytes const = 1; + + // Len specifies that this field must be the specified number of bytes + optional uint64 len = 13; + + // MinLen specifies that this field must be the specified number of bytes + // at a minimum + optional uint64 min_len = 2; + + // MaxLen specifies that this field must be the specified number of bytes + // at a maximum + optional uint64 max_len = 3; + + // Pattern specifies that this field must match against the specified + // regular expression (RE2 syntax). The included expression should elide + // any delimiters. + optional string pattern = 4; + + // Prefix specifies that this field must have the specified bytes at the + // beginning of the string. + optional bytes prefix = 5; + + // Suffix specifies that this field must have the specified bytes at the + // end of the string. + optional bytes suffix = 6; + + // Contains specifies that this field must have the specified bytes + // anywhere in the string. + optional bytes contains = 7; + + // In specifies that this field must be equal to one of the specified + // values + repeated bytes in = 8; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated bytes not_in = 9; + + // WellKnown rules provide advanced constraints against common byte + // patterns + oneof well_known { + // Ip specifies that the field must be a valid IP (v4 or v6) address in + // byte format + bool ip = 10; + + // Ipv4 specifies that the field must be a valid IPv4 address in byte + // format + bool ipv4 = 11; + + // Ipv6 specifies that the field must be a valid IPv6 address in byte + // format + bool ipv6 = 12; + } + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 14; +} + +// EnumRules describe the constraints applied to enum values +message EnumRules { + // Const specifies that this field must be exactly the specified value + optional int32 const = 1; + + // DefinedOnly specifies that this field must be only one of the defined + // values for this enum, failing on any undefined value. + optional bool defined_only = 2; + + // In specifies that this field must be equal to one of the specified + // values + repeated int32 in = 3; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated int32 not_in = 4; +} + +// MessageRules describe the constraints applied to embedded message values. +// For message-type fields, validation is performed recursively. +message MessageRules { + // Skip specifies that the validation rules of this field should not be + // evaluated + optional bool skip = 1; + + // Required specifies that this field must be set + optional bool required = 2; +} + +// RepeatedRules describe the constraints applied to `repeated` values +message RepeatedRules { + // MinItems specifies that this field must have the specified number of + // items at a minimum + optional uint64 min_items = 1; + + // MaxItems specifies that this field must have the specified number of + // items at a maximum + optional uint64 max_items = 2; + + // Unique specifies that all elements in this field must be unique. This + // constraint is only applicable to scalar and enum types (messages are not + // supported). + optional bool unique = 3; + + // Items specifies the constraints to be applied to each item in the field. + // Repeated message fields will still execute validation against each item + // unless skip is specified here. + optional FieldRules items = 4; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 5; +} + +// MapRules describe the constraints applied to `map` values +message MapRules { + // MinPairs specifies that this field must have the specified number of + // KVs at a minimum + optional uint64 min_pairs = 1; + + // MaxPairs specifies that this field must have the specified number of + // KVs at a maximum + optional uint64 max_pairs = 2; + + // NoSparse specifies values in this field cannot be unset. This only + // applies to map's with message value types. + optional bool no_sparse = 3; + + // Keys specifies the constraints to be applied to each key in the field. + optional FieldRules keys = 4; + + // Values specifies the constraints to be applied to the value of each key + // in the field. Message values will still have their validations evaluated + // unless skip is specified here. + optional FieldRules values = 5; + + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + optional bool ignore_empty = 6; +} + +// AnyRules describe constraints applied exclusively to the +// `google.protobuf.Any` well-known type +message AnyRules { + // Required specifies that this field must be set + optional bool required = 1; + + // In specifies that this field's `type_url` must be equal to one of the + // specified values. + repeated string in = 2; + + // NotIn specifies that this field's `type_url` must not be equal to any of + // the specified values. + repeated string not_in = 3; +} + +// DurationRules describe the constraints applied exclusively to the +// `google.protobuf.Duration` well-known type +message DurationRules { + // Required specifies that this field must be set + optional bool required = 1; + + // Const specifies that this field must be exactly the specified value + optional google.protobuf.Duration const = 2; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional google.protobuf.Duration lt = 3; + + // Lt specifies that this field must be less than the specified value, + // inclusive + optional google.protobuf.Duration lte = 4; + + // Gt specifies that this field must be greater than the specified value, + // exclusive + optional google.protobuf.Duration gt = 5; + + // Gte specifies that this field must be greater than the specified value, + // inclusive + optional google.protobuf.Duration gte = 6; + + // In specifies that this field must be equal to one of the specified + // values + repeated google.protobuf.Duration in = 7; + + // NotIn specifies that this field cannot be equal to one of the specified + // values + repeated google.protobuf.Duration not_in = 8; +} + +// TimestampRules describe the constraints applied exclusively to the +// `google.protobuf.Timestamp` well-known type +message TimestampRules { + // Required specifies that this field must be set + optional bool required = 1; + + // Const specifies that this field must be exactly the specified value + optional google.protobuf.Timestamp const = 2; + + // Lt specifies that this field must be less than the specified value, + // exclusive + optional google.protobuf.Timestamp lt = 3; + + // Lte specifies that this field must be less than the specified value, + // inclusive + optional google.protobuf.Timestamp lte = 4; + + // Gt specifies that this field must be greater than the specified value, + // exclusive + optional google.protobuf.Timestamp gt = 5; + + // Gte specifies that this field must be greater than the specified value, + // inclusive + optional google.protobuf.Timestamp gte = 6; + + // LtNow specifies that this must be less than the current time. LtNow + // can only be used with the Within rule. + optional bool lt_now = 7; + + // GtNow specifies that this must be greater than the current time. GtNow + // can only be used with the Within rule. + optional bool gt_now = 8; + + // Within specifies that this field must be within this duration of the + // current time. This constraint can be used alone or with the LtNow and + // GtNow rules. + optional google.protobuf.Duration within = 9; +} diff --git a/src/grpc/client.ts b/src/grpc/client.ts index 1b429ed..d29886c 100644 --- a/src/grpc/client.ts +++ b/src/grpc/client.ts @@ -2,34 +2,48 @@ import path from 'path' import protoLoader from '@grpc/proto-loader' import grpc from '@grpc/grpc-js' -interface Version { - id: number - version: string +// req dto +interface CreateUserDto { + email: string + name?: string } -interface VersionDto {} - -interface GetUserByEmail { - email: string -} - -export interface User { +interface UpdateUserDto { id: number - email: string token?: string description?: string - is_admin?: boolean +} + +interface GetUserByTokenDto { + token: string +} + +interface GetUserByEmailDto { + email: string +} + +interface ListUserDto { + page: number + iser_ids: number[] +} + +interface CreateChatDto { + name?: string + users: { user_id: number; is_admin?: boolean }[] +} + +interface UpdateChat { + id: number + users: { user_id: number; is_admin?: boolean }[] +} + +interface GetChatDto { + id: string } interface ListChatDto { page: number - user_ids?: number[] - chat_ids?: string[] -} - -interface ListMessageDto { - page: number - chat_id: string + user_id: number } interface CreateMessageDto { @@ -40,45 +54,103 @@ interface CreateMessageDto { video?: string file?: string } +interface UpdateMessageDto { + id: number + chat_id: string + text?: string + image?: string + video?: string + file?: string +} +interface GetMessageDto { + id: number +} +interface ListMessageDto { + page: number + chat_id: string +} + +interface Version { + id: number + version: string +} + +interface VersionDto {} + +export interface User { + id: number + email: string + token?: string + description?: string + is_admin?: boolean +} + +export interface Chat { + id: string + type_id: number + name: string + users: { user_id: number; is_admin?: boolean }[] +} interface Message { id: number user_id: number text?: string - image: string - video: string - file: string -} - -interface Chat { - id: string - type_id: number - users: User[] + image?: string + video?: string + file?: string + created_at: string + updated_at: string } interface Response { data: T } -enum Services { - getVersion = 'getVersion', - createUser = 'createUser', - getUserByEmail = 'getUserByEmail', - listUser = 'listUser', - listChat = 'listChat', - listMessage = 'listMessage', - createMessage = 'createMessage', +interface Services { + createUser: (data: CreateUserDto) => { data: User } + updateUser: (data: UpdateUserDto) => { data: User } + getUserByToken: (data: GetUserByTokenDto) => { data: User } + getUserByEmail: (data: GetUserByEmailDto) => { data: User } + listUser: (data: ListUserDto) => { data: User[] } + createChat: (data: CreateChatDto) => { data: Chat } + updateChat: (data: UpdateChat) => { data: Chat } + getChat: (data: GetChatDto) => { data: Chat } + listChat: (data: ListChatDto) => { data: Chat[] } + createMessage: (data: CreateMessageDto) => { data: Message } + updateMessage: (data: UpdateMessageDto) => { data: Message } + getMessage: (data: GetMessageDto) => { data: Message } + listMessage: (data: ListMessageDto) => { data: Message[] } + getVersion: (data: VersionDto) => { data: Version } +} + +enum ServiceName { + CreateUser = 'createUser', + UpdateUser = 'updateUser', + GetUserByToken = 'getUserByToken', + GetUserByEmail = 'getUserByEmail', + ListUser = 'listUser', + + CreateChat = 'createChat', + UpdateChat = 'updateChat', + GetChat = 'getChat', + ListChat = 'listChat', + + CreateMessage = 'createMessage', + UpdateMessage = 'updateMessage', + GetMessage = 'getMessage', + ListMessage = 'listMessage', + + GetVersion = 'getVersion', } class GrpcClient { - messageClient: any + messageClient: Services constructor() { console.log('Grpc Client init') const PROTO_PATH = path.resolve('./proto/message.proto') - console.log('PROTO_PATH', PROTO_PATH) - const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, @@ -93,10 +165,12 @@ class GrpcClient { this.messageClient = new messageProto.MessageService('localhost:8070', grpc.credentials.createInsecure()) } - private toPromise(client: any, methodName: Services) { + private toPromise(client: any, methodName: ServiceName) { + const service = client[methodName] + return (request: T): Promise> => { return new Promise((resolve, reject) => { - client[methodName](request, (error: Error, response: Response) => { + service(request, (error: Error, response: Response) => { if (error) reject(error.message) else resolve(response) }) @@ -105,23 +179,25 @@ class GrpcClient { } getVersion(dto: VersionDto) { - return this.toPromise(this.messageClient, Services.getVersion)(dto) + const service = this.messageClient[ServiceName.GetVersion] + + return this.toPromise(this.messageClient, ServiceName.GetVersion)(dto) } - getUserByEmail(dto: GetUserByEmail) { - return this.toPromise(this.messageClient, Services.getUserByEmail)(dto) - } + // getUserByEmail(dto: GetUserByEmail) { + // return this.toPromise(this.messageClient, ServiceName.GetUserByEmail)(dto) + // } getChatsByUser(dto: ListChatDto) { - return this.toPromise(this.messageClient, Services.listChat)(dto) + return this.toPromise(this.messageClient, ServiceName.ListChat)(dto) } getMessagesByChatId(dto: ListMessageDto) { - return this.toPromise(this.messageClient, Services.listMessage)(dto) + return this.toPromise(this.messageClient, ServiceName.ListMessage)(dto) } createMessage(dto: CreateMessageDto) { - return this.toPromise(this.messageClient, Services.createMessage)(dto) + return this.toPromise(this.messageClient, ServiceName.CreateMessage)(dto) } } diff --git a/src/handles.ts b/src/handles.ts index d8880c2..02a3ff0 100644 --- a/src/handles.ts +++ b/src/handles.ts @@ -49,10 +49,10 @@ export async function login(req: Request) { } export async function upgrade(req: Request, server: Bun.Server) { - const userId = await checkRequest(req) - if (!userId) return new Response('Invalid token', { status: HttpStatusCodes.NOT_FOUND }) + const payload = await checkRequest(req) + if (!payload) return new Response('Invalid token', { status: HttpStatusCodes.NOT_FOUND }) - const success = server.upgrade(req, { data: { userId: userId } }) + const success = server.upgrade(req, { data: { userId: +payload.sub, email: payload.email } }) if (success) return undefined return new Response('Upgrade failed', { status: HttpStatusCodes.BAD_REQUEST }) } @@ -63,11 +63,7 @@ async function checkRequest(req: Request) { const token = url.searchParams.get('token') if (!token) return null - const payload = await verifyAccessToken(token) - - console.log('token', token) - console.log(payload) - return +payload.sub + return await verifyAccessToken(token) } catch (error) { if (error instanceof errors.JWTInvalid) { console.log('invalid') diff --git a/src/index.ts b/src/index.ts index 8fb833a..2f61a1e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,13 +24,15 @@ const server = Bun.serve({ async open(ws) { try { const ipAddr = ws.remoteAddress - console.log('ipAddr', ipAddr) + // console.log('ipAddr', ipAddr) + + const user = ws.data const chatResponse = await client.getChatsByUser({ page: 0, user_ids: [1] }) chatResponse.data.forEach((el) => ws.subscribe(el.id)) - console.log('chats', chatResponse.data) - console.log('subscriptions', ws.subscriptions) + // console.log('chats', chatResponse.data) + // console.log('subscriptions', ws.subscriptions) ws.send(JSON.stringify({ type: 'CHATS', ...chatResponse })) } catch (error) { @@ -57,7 +59,7 @@ const server = Bun.serve({ return } - if (o.type === 'CREATE_MESSAGE') { + if (o.type === 'MESSAGE_CREATE') { console.log('create') const message = await client.createMessage({ chat_id: o.data.chat_id, @@ -69,7 +71,7 @@ const server = Bun.serve({ } if (o.type === 'GET_MESSAGES') { - console.log('get') + console.log('GET_MESSAGES') const messages = await client.getMessagesByChatId({ chat_id: o.data.chat_id, page: 1 }) server.publish(o.data.chat_id, JSON.stringify({ type: 'MESSAGES', ...messages })) } diff --git a/src/types/types.ts b/src/types/types.ts index e17045d..88ecbe7 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -2,6 +2,18 @@ export interface WebSocketData { chatId?: string token?: string userId: number + email: string +} + +export enum DATATYPE { + CHATS_LIST = 'CHATS_LIST', + CHATS_CREATE = 'CHATS_CREATE', + USERS_LIST = 'USERS_LIST', + USER_GET = 'USER_GET', + MESSAGES_LIST = 'MESSAGES_LIST', + MESSAGE_CREATE = 'MESSAGE_CREATE', + STATUS = 'STATUS', + ERROR = 'ERROR', } export type LoginDto = { email: string } @@ -14,7 +26,7 @@ interface ListMessages { } interface CreateMessage { - type: 'CREATE_MESSAGE' + type: 'MESSAGE_CREATE' data: { chat_id: string text: string @@ -32,4 +44,4 @@ interface MessageData { text: string } -export type WsData = ListMessages|CreateMessage +export type WsData = ListMessages | CreateMessage