Skip to content

Commit

Permalink
Add isIpPrefix (#99)
Browse files Browse the repository at this point in the history
- [x] protovalidate-go:
bufbuild/protovalidate-go#53
- [x] protovalidate-cc:
bufbuild/protovalidate-cc#45 (via @paina)
- [x] protovalidate-java:
bufbuild/protovalidate-java#39
- [x] protovalidate-python:
bufbuild/protovalidate-python#78

---------

Co-authored-by: Chris Roche <github@rodaine.com>
  • Loading branch information
higebu and rodaine committed Oct 30, 2023
1 parent 8fa0222 commit c4ad688
Show file tree
Hide file tree
Showing 7 changed files with 1,569 additions and 738 deletions.
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

0 comments on commit c4ad688

Please sign in to comment.