Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add isIpPrefix #99

Merged
merged 4 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/cel.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ in `protovalidate`. These are free to use within [custom constraints](custom-con
| `isEmail` | `string.isEmail() -> bool` | Test whether the string is a valid email address |
| `isHostname` | `string.isHostname() -> bool` | Test whether the string is a valid hostname |
| `isIp` | `string.isIp() -> bool`<br/>`string.isIp(4) -> bool`<br/>`string.isIp(6) -> bool` | Test whether the string is a valid IP address, optionally limited to a specific version (v4 or v6) |
| `isIpPrefix` | `string.isIpPrefix() -> bool`<br/>`string.isIpPrefix(4) -> bool`<br/>`string.isIpPrefix(6) -> bool`</br>`string.isIpPrefix(true) -> bool`<br/>`string.isIpPrefix(4,true) -> bool`<br/>`string.isIpPrefix(6,true) -> bool` | Test whether the string is a valid IP with prefix length, optionally limited to a specific version (v4 or v6) and an appropriate network address (true or false) |
| `isUriRef` | `string.isUriRef() -> bool` | Tests whether the string is a valid (absolute or relative) URI |
| `isUri` | `string.isUri() -> bool` | Tests whether the string is a valid absolute URI |
| `unique` | `list(bool).unique() -> bool`<br/>`list(int).unique() -> bool`<br/>`list(uint).unique() -> bool`<br/>`list(double).unique() -> bool`<br/>`list(string).unique() -> bool`<br/>`list(bytes).unique() -> bool` | Test whether the items in the list are all unique. |
Expand Down
21 changes: 21 additions & 0 deletions examples/cel_string_is_ip.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import "buf/validate/validate.proto";

service LocationService {
rpc LocationForIp(LocationForIpRequest) returns (LocationForIpResponse);
rpc LocationForIpPrefix(LocationForIpPrefixRequest) returns (LocationForIpPrefixResponse);
}

message LocationForIpRequest {
Expand All @@ -36,3 +37,23 @@ message LocationForIpRequest {
message LocationForIpResponse {
// ...
}

message LocationForIpPrefixRequest {
string ip_prefix = 1 [(buf.validate.field).cel = {
id: "valid_prefix",
message: ".",
// `some_string.isIpPrefix()` returns whether the string is a valid ip with prefix length.
// `isIpPrefix(4)` returns whether a string is an ipv4 with prefix length.
// `isIpPrefix(6)` returns whether a string is an ipv6 with prefix length.
// `isIpPrefix(true)` returns whether a string is an ip prefix.
// `isIpPrefix(4, true)` returns whether a string is an ipv4 prefix.
// `isIpPrefix(6, true)` returns whether a string is an ipv6 prefix.
// In this case, it validates that field `ip_prefix` must be a valid ip with
// prefix length, either ipv4 or ipv6.
expression: "this.isIpPrefix()"
}];
}

message LocationForIpPrefixResponse {
// ...
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ message StringIPv4 {
message StringIPv6 {
string val = 1 [(buf.validate.field).string.ipv6 = true];
}
message StringIPWithPrefixLen {
string val = 1 [(buf.validate.field).string.ip_with_prefixlen = true];
}
message StringIPv4WithPrefixLen {
string val = 1 [(buf.validate.field).string.ipv4_with_prefixlen = true];
}
message StringIPv6WithPrefixLen {
string val = 1 [(buf.validate.field).string.ipv6_with_prefixlen = true];
}
message StringIPPrefix {
string val = 1 [(buf.validate.field).string.ip_prefix = true];
}
message StringIPv4Prefix {
string val = 1 [(buf.validate.field).string.ipv4_prefix = true];
}
message StringIPv6Prefix {
string val = 1 [(buf.validate.field).string.ipv6_prefix = true];
}
message StringURI {
string val = 1 [(buf.validate.field).string.uri = true];
}
Expand Down
102 changes: 102 additions & 0 deletions proto/protovalidate/buf/validate/validate.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,108 @@ message StringRules {
expression: "!this.matches('^[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}$') ? 'value must be a valid UUID' : ''"
}];

// `ip_with_prefixlen` specifies that the field value must be a valid IP (v4 or v6)
// address with prefix length. If the field value isn't a valid IP with prefix
// length, an error message will be generated.
//
//
// ```proto
// message MyString {
// // value must be a valid IP with prefix length
// string value = 1 [(buf.validate.field).string.ip_with_prefixlen = true];
// }
// ```
bool ip_with_prefixlen = 26 [(priv.field).cel = {
id: "string.ip_with_prefixlen",
message: "value must be a valid IP prefix",
expression: "this.isIpPrefix()",
}];

// `ipv4_with_prefixlen` specifies that the field value must be a valid
// IPv4 address with prefix.
// If the field value isn't a valid IPv4 address with prefix length,
// an error message will be generated.
//
// ```proto
// message MyString {
// // value must be a valid IPv4 address with prefix lentgh
// string value = 1 [(buf.validate.field).string.ipv4_with_prefixlen = true];
// }
// ```
bool ipv4_with_prefixlen = 27 [(priv.field).cel = {
id: "string.ipv4_with_prefixlen",
message: "value must be a valid IPv4 address with prefix length",
expression: "this.isIpPrefix(4)"
}];

// `ipv6_with_prefixlen` specifies that the field value must be a valid
// IPv6 address with prefix length.
// If the field value is not a valid IPv6 address with prefix length,
// an error message will be generated.
//
// ```proto
// message MyString {
// // value must be a valid IPv6 address prefix length
// string value = 1 [(buf.validate.field).string.ipv6_with_prefixlen = true];
// }
// ```
bool ipv6_with_prefixlen = 28 [(priv.field).cel = {
id: "string.ipv6_with_prefixlen",
message: "value must be a valid IPv6 address with prefix length",
expression: "this.isIpPrefix(6)",
}];

// `ip_prefix` specifies that the field value must be a valid IP (v4 or v6) prefix.
// If the field value isn't a valid IP prefix, an error message will be
// generated. The prefix must have all zeros for the masked bits of the prefix (e.g.,
// `127.0.0.0/16`, not `127.0.0.1/16`).
//
// ```proto
// message MyString {
// // value must be a valid IP prefix
// string value = 1 [(buf.validate.field).string.ip_prefix = true];
// }
// ```
bool ip_prefix = 29 [(priv.field).cel = {
id: "string.ip_prefix",
message: "value must be a valid IP prefix",
expression: "this.isIpPrefix(true)",
}];

// `ipv4_prefix` specifies that the field value must be a valid IPv4
// prefix. If the field value isn't a valid IPv4 prefix, an error message
// will be generated. The prefix must have all zeros for the masked bits of
// the prefix (e.g., `127.0.0.0/16`, not `127.0.0.1/16`).
//
// ```proto
// message MyString {
// // value must be a valid IPv4 prefix
// string value = 1 [(buf.validate.field).string.ipv4_prefix = true];
// }
// ```
bool ipv4_prefix = 30 [(priv.field).cel = {
id: "string.ipv4_prefix",
message: "value must be a valid IPv4 prefix",
expression: "this.isIpPrefix(4, true)"
}];

// `ipv6_prefix` specifies that the field value must be a valid IPv6 prefix.
// If the field value is not a valid IPv6 prefix, an error message will be
// generated. The prefix must have all zeros for the masked bits of the prefix
// (e.g., `2001:db8::/48`, not `2001:db8::1/48`).
//
// ```proto
// message MyString {
// // value must be a valid IPv6 prefix
// string value = 1 [(buf.validate.field).string.ipv6_prefix = true];
// }
// ```
bool ipv6_prefix = 31 [(priv.field).cel = {
id: "string.ipv6_prefix",
message: "value must be a valid IPv6 prefix",
expression: "this.isIpPrefix(6, true)",
}];

// `well_known_regex` specifies a common well-known pattern
// defined as a regex. If the field value doesn't match the well-known
// regex, an error message will be generated.
Expand Down
Loading