Request Validation logic moved into a helper (#296)
* Move all the validation logic into a helper tool. * Adding tests for verifier helpers.
This commit is contained in:
1 parent
bc32272ca7
commit
e423b6589e
10 files changed
+740
-721
No files matched your search
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
@@ -21,7 +19,6 @@ import (
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -67,7 +64,7 @@ func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest)
|
||||
return &pbs.ListAccountsResponse{Items: ul}, nil
|
||||
}
|
||||
|
||||
// GetAccounts implements the interface pbs.AccountServiceServer.
|
||||
// GetAccount implements the interface pbs.AccountServiceServer.
|
||||
func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*pbs.GetAccountResponse, error) {
|
||||
authResults := auth.Verify(ctx)
|
||||
if authResults.Error != nil {
|
||||
@@ -353,76 +350,58 @@ func toProto(in *password.Account) (*pb.Account, error) {
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetAccountRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AccountPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(password.AccountPrefix, req, func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(password.AuthMethodPrefix, req.GetAuthMethodId()) {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateAccountRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
item := req.GetItem()
|
||||
if item.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetAuthMethodId() != "" {
|
||||
badFields["auth_method_id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
switch auth.SubtypeFromId(req.GetAuthMethodId()) {
|
||||
case auth.PasswordSubtype:
|
||||
if item.GetType() != "" && item.GetType() != auth.PasswordSubtype.String() {
|
||||
badFields["type"] = "Doesn't match the parent resource's type."
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.GetItem().GetAuthMethodId() != "" {
|
||||
badFields["auth_method_id"] = "This is a read only field."
|
||||
}
|
||||
pwAttrs := &pb.PasswordAccountAttributes{}
|
||||
if err := handlers.StructToProto(item.GetAttributes(), pwAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
switch auth.SubtypeFromId(req.GetAuthMethodId()) {
|
||||
case auth.PasswordSubtype:
|
||||
if req.GetItem().GetType() != "" && req.GetItem().GetType() != auth.PasswordSubtype.String() {
|
||||
badFields["type"] = "Doesn't match the parent resource's type."
|
||||
}
|
||||
pwAttrs := &pb.PasswordAccountAttributes{}
|
||||
if err := handlers.StructToProto(req.GetItem().GetAttributes(), pwAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
}
|
||||
if pwAttrs.GetLoginName() == "" {
|
||||
badFields["login_name"] = "This is a required field for this type."
|
||||
}
|
||||
}
|
||||
if pwAttrs.GetLoginName() == "" {
|
||||
badFields["login_name"] = "This is a required field for this type."
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateAccountRequest) error {
|
||||
return handlers.ValidateUpdateRequest(password.AccountPrefix, req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteAccountRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if !validId(req.GetId(), password.AccountPrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateDeleteRequest(password.AccountPrefix, req, func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(password.AuthMethodPrefix, req.GetAuthMethodId()) {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListAccountsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
if !handlers.ValidId(password.AuthMethodPrefix, req.GetAuthMethodId()) {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
@@ -433,10 +412,10 @@ func validateListRequest(req *pbs.ListAccountsRequest) error {
|
||||
|
||||
func validateChangePasswordRequest(req *pbs.ChangePasswordRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AccountPrefix+"_") {
|
||||
if !handlers.ValidId(password.AccountPrefix, req.GetId()) {
|
||||
badFields["id"] = "Improperly formatted identifier."
|
||||
}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
if !handlers.ValidId(password.AuthMethodPrefix, req.GetAuthMethodId()) {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -456,10 +435,10 @@ func validateChangePasswordRequest(req *pbs.ChangePasswordRequest) error {
|
||||
|
||||
func validateSetPasswordRequest(req *pbs.SetPasswordRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AccountPrefix+"_") {
|
||||
if !handlers.ValidId(password.AccountPrefix, req.GetId()) {
|
||||
badFields["id"] = "Improperly formatted identifier."
|
||||
}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
if !handlers.ValidId(password.AuthMethodPrefix, req.GetAuthMethodId()) {
|
||||
badFields["auth_method_id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -470,54 +449,3 @@ func validateSetPasswordRequest(req *pbs.SetPasswordRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateAccountRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AccountPrefix+"_") {
|
||||
badFields["id"] = "Improperly formatted identifier."
|
||||
}
|
||||
if !validId(req.GetAuthMethodId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["auth_method_id"] = "Improperly formatted identifier."
|
||||
}
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update this resource."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetAuthMethodId() != "" {
|
||||
badFields["auth_method_id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
@@ -65,7 +64,7 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe
|
||||
return &pbs.ListAuthMethodsResponse{Items: ul}, nil
|
||||
}
|
||||
|
||||
// GetAuthMethods implements the interface pbs.AuthMethodServiceServer.
|
||||
// GetAuthMethod implements the interface pbs.AuthMethodServiceServer.
|
||||
func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodRequest) (*pbs.GetAuthMethodResponse, error) {
|
||||
authResults := auth.Verify(ctx)
|
||||
if authResults.Error != nil {
|
||||
@@ -286,106 +285,43 @@ func toProto(in *password.AuthMethod) (*pb.AuthMethod, error) {
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetAuthMethodRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted id."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListAuthMethodsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(password.AuthMethodPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateAuthMethodRequest) error {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
switch auth.SubtypeFromType(item.GetType()) {
|
||||
case auth.PasswordSubtype:
|
||||
pwAttrs := &pb.PasswordAuthMethodAttributes{}
|
||||
if err := handlers.StructToProto(item.GetAttributes(), pwAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
switch auth.SubtypeFromType(req.GetItem().GetType()) {
|
||||
case auth.PasswordSubtype:
|
||||
pwAttrs := &pb.PasswordAuthMethodAttributes{}
|
||||
if err := handlers.StructToProto(req.GetItem().GetAttributes(), pwAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
}
|
||||
default:
|
||||
badFields["type"] = fmt.Sprintf("This is a required field and must be %q.", auth.PasswordSubtype.String())
|
||||
}
|
||||
default:
|
||||
badFields["type"] = fmt.Sprintf("This is a required field and must be %q.", auth.PasswordSubtype.String())
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateAuthMethodRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["id"] = "Improperly formatted identifier."
|
||||
}
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update this resource."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
return handlers.ValidateUpdateRequest(password.AuthMethodPrefix, req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.GetItem().GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteAuthMethodRequest) error {
|
||||
return handlers.ValidateDeleteRequest(password.AuthMethodPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(_ *pbs.ListAuthMethodsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), password.AuthMethodPrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
@@ -19,10 +17,6 @@ import (
|
||||
|
||||
const orgIdFieldName = "org_id"
|
||||
|
||||
var (
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
// Service handles request as described by the pbs.AuthTokenServiceServer interface.
|
||||
type Service struct {
|
||||
repoFn func() (*authtoken.Repository, error)
|
||||
@@ -57,7 +51,7 @@ func (s Service) ListAuthTokens(ctx context.Context, req *pbs.ListAuthTokensRequ
|
||||
return &pbs.ListAuthTokensResponse{Items: ul}, nil
|
||||
}
|
||||
|
||||
// GetAuthTokens implements the interface pbs.AuthTokenServiceServer.
|
||||
// GetAuthToken implements the interface pbs.AuthTokenServiceServer.
|
||||
func (s Service) GetAuthToken(ctx context.Context, req *pbs.GetAuthTokenRequest) (*pbs.GetAuthTokenResponse, error) {
|
||||
authResults := auth.Verify(ctx)
|
||||
if authResults.Error != nil {
|
||||
@@ -159,39 +153,17 @@ func toProto(in *authtoken.AuthToken) *pb.AuthToken {
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetAuthTokenRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), authtoken.AuthTokenPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted user id."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(authtoken.AuthTokenPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteAuthTokenRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), authtoken.AuthTokenPrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateDeleteRequest(authtoken.AuthTokenPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListAuthTokensRequest) error {
|
||||
func validateListRequest(_ *pbs.ListAuthTokensRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
@@ -21,7 +19,6 @@ import (
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -373,80 +370,19 @@ func toProto(in *iam.Group, members []*iam.GroupMember) *pb.Group {
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetGroupRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted group id."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(iam.GroupPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateGroupRequest) error {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateGroupRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
badFields["group_id"] = "Improperly formatted path identifier."
|
||||
}
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update a group."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
return handlers.ValidateUpdateRequest(iam.GroupPrefix, req, req.GetItem(), handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteGroupRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateDeleteRequest(iam.GroupPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListGroupsRequest) error {
|
||||
@@ -459,7 +395,7 @@ func validateListRequest(req *pbs.ListGroupsRequest) error {
|
||||
|
||||
func validateAddGroupMembersRequest(req *pbs.AddGroupMembersRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
if !handlers.ValidId(iam.GroupPrefix, req.GetId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -481,7 +417,7 @@ func validateAddGroupMembersRequest(req *pbs.AddGroupMembersRequest) error {
|
||||
|
||||
func validateSetGroupMembersRequest(req *pbs.SetGroupMembersRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
if !handlers.ValidId(iam.GroupPrefix, req.GetId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -500,7 +436,7 @@ func validateSetGroupMembersRequest(req *pbs.SetGroupMembersRequest) error {
|
||||
|
||||
func validateRemoveGroupMembersRequest(req *pbs.RemoveGroupMembersRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.GroupPrefix+"_") {
|
||||
if !handlers.ValidId(iam.GroupPrefix, req.GetId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -514,11 +450,3 @@ func validateRemoveGroupMembersRequest(req *pbs.RemoveGroupMembersRequest) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package host_catalogs
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
|
||||
@@ -21,7 +19,6 @@ import (
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -260,14 +257,37 @@ func toProto(in *static.HostCatalog) *pb.HostCatalog {
|
||||
// * The type asserted by the ID and/or field is known
|
||||
// * If relevant, the type derived from the id prefix matches what is claimed by the type field
|
||||
func validateGetRequest(req *pbs.GetHostCatalogRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(static.HostCatalogPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error {
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
switch host.SubtypeFromType(req.GetItem().GetType()) {
|
||||
case host.StaticSubtype:
|
||||
shcAttrs := &pb.StaticHostCatalogDetails{}
|
||||
if err := handlers.StructToProto(req.GetItem().GetAttributes(), shcAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
}
|
||||
default:
|
||||
badFields["type"] = fmt.Sprintf("This is a required field and must be %q.", host.StaticSubtype.String())
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateHostCatalogRequest) error {
|
||||
return handlers.ValidateUpdateRequest(static.HostCatalogPrefix, req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.GetItem().GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteHostCatalogRequest) error {
|
||||
return handlers.ValidateDeleteRequest(static.HostCatalogPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListHostCatalogsRequest) error {
|
||||
@@ -277,93 +297,3 @@ func validateListRequest(req *pbs.ListHostCatalogsRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
badFields["item"] = "This field is required."
|
||||
}
|
||||
if item.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
switch host.SubtypeFromType(item.GetType()) {
|
||||
case host.StaticSubtype:
|
||||
shcAttrs := &pb.StaticHostCatalogDetails{}
|
||||
if err := handlers.StructToProto(item.GetAttributes(), shcAttrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
}
|
||||
default:
|
||||
badFields["type"] = fmt.Sprintf("This is a required field and must be %q.", host.StaticSubtype.String())
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This field is read only."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This field is read only."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This field is read only."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateHostCatalogRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "This field is required."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteHostCatalogRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
|
||||
@@ -295,116 +294,71 @@ func toProto(in *static.Host, members []*static.HostSetMember) (*pb.Host, error)
|
||||
// * The type asserted by the ID and/or field is known
|
||||
// * If relevant, the type derived from the id prefix matches what is claimed by the type field
|
||||
func validateGetRequest(req *pbs.GetHostRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetHostCatalogId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if !validId(req.GetId(), static.HostPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(static.HostPrefix, req, func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateHostRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetHostCatalogId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", map[string]string{"item": "this field is required."})
|
||||
}
|
||||
|
||||
ha := &pb.StaticHostAttributes{}
|
||||
if err := handlers.StructToProto(item.GetAttributes(), ha); err != nil {
|
||||
badFields["attributes"] = "Incorrectly formatted attribute for this type."
|
||||
}
|
||||
|
||||
if ha.GetAddress() == nil {
|
||||
badFields["attributes.address"] = "This field is required."
|
||||
}
|
||||
|
||||
switch host.SubtypeFromId(req.GetHostCatalogId()) {
|
||||
case host.StaticSubtype:
|
||||
if item.GetType() != "" && item.GetType() != host.StaticSubtype.String() {
|
||||
badFields["type"] = "Doesn't match the parent resource's type."
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
attrs := &pb.StaticHostAttributes{}
|
||||
if err := handlers.StructToProto(item.GetAttributes(), attrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
|
||||
if req.GetItem().GetHostCatalogId() != "" {
|
||||
badFields["host_catalog_id"] = "This field is read only."
|
||||
}
|
||||
if attrs.GetAddress() == nil {
|
||||
badFields["attributes.address"] = "This is a required field for this type."
|
||||
switch host.SubtypeFromId(req.GetHostCatalogId()) {
|
||||
case host.StaticSubtype:
|
||||
if req.GetItem().GetType() != "" && req.GetItem().GetType() != host.StaticSubtype.String() {
|
||||
badFields["type"] = "Doesn't match the parent resource's type."
|
||||
}
|
||||
attrs := &pb.StaticHostAttributes{}
|
||||
if err := handlers.StructToProto(req.GetItem().GetAttributes(), attrs); err != nil {
|
||||
badFields["attributes"] = "Attribute fields do not match the expected format."
|
||||
}
|
||||
if attrs.GetAddress() == nil {
|
||||
badFields["attributes.address"] = "This is a required field for this type."
|
||||
}
|
||||
}
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This field is read only."
|
||||
}
|
||||
if item.GetHostCatalogId() != "" {
|
||||
badFields["host_catalog_id"] = "This field is read only."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This field is read only."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This field is read only."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateHostRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), static.HostPrefix+"_") {
|
||||
badFields["id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if !validId(req.GetHostCatalogId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
return handlers.ValidateUpdateRequest(static.HostPrefix, req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if req.GetItem().GetHostCatalogId() != "" {
|
||||
badFields["host_catalog_id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if req.GetItem().GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "This field is required."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetType() != "" {
|
||||
badFields["type"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetHostCatalogId() != "" {
|
||||
badFields["host_catalog_id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
func validateDeleteRequest(req *pbs.DeleteHostRequest) error {
|
||||
return handlers.ValidateDeleteRequest(static.HostPrefix, req, func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListHostsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetHostCatalogId(), static.HostCatalogPrefix+"_") {
|
||||
if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
@@ -412,25 +366,3 @@ func validateListRequest(req *pbs.ListHostsRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteHostRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetHostCatalogId(), static.HostCatalogPrefix+"_") {
|
||||
badFields["host_catalog_id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if !validId(req.GetId(), static.HostPrefix+"_") {
|
||||
badFields["id"] = "The field is incorrectly formatted."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid arguments provided.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
@@ -16,6 +14,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/iam/store"
|
||||
"github.com/hashicorp/boundary/internal/perms"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
@@ -23,7 +22,6 @@ import (
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -528,105 +526,54 @@ func toProto(in *iam.Role, principals []iam.PrincipalRole, grants []*iam.RoleGra
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetRoleRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.RolePrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted role id."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(iam.RolePrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateRoleRequest, scope *scopes.ScopeInfo) error {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetGrantScopeId() != nil && scope.GetType() == "project" {
|
||||
if item.GetGrantScopeId().Value != scope.GetId() {
|
||||
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
|
||||
func validateCreateRequest(req *pbs.CreateRoleRequest, s *scopes.ScopeInfo) error {
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item.GetGrantScopeId() != nil && s.GetType() == scope.Project.String() {
|
||||
if item.GetGrantScopeId().Value != s.GetId() {
|
||||
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
|
||||
}
|
||||
}
|
||||
}
|
||||
if item.GetPrincipals() != nil {
|
||||
badFields["principals"] = "This is a read only field."
|
||||
}
|
||||
if item.GetGrants() != nil {
|
||||
badFields["grant_strings"] = "This is a read only field."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
if item.GetPrincipals() != nil {
|
||||
badFields["principals"] = "This is a read only field."
|
||||
}
|
||||
if item.GetGrants() != nil {
|
||||
badFields["grant_strings"] = "This is a read only field."
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateRoleRequest, scope *scopes.ScopeInfo) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.RolePrefix+"_") {
|
||||
badFields["role_id"] = "Improperly formatted path identifier."
|
||||
}
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update a role."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetPrincipalIds() != nil {
|
||||
badFields["principal_ids"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetPrincipals() != nil {
|
||||
badFields["principals"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetGrants() != nil {
|
||||
badFields["grants"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetGrantStrings() != nil {
|
||||
badFields["grant_strings"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetGrantScopeId() != nil && scope.GetType() == "project" {
|
||||
if item.GetGrantScopeId().Value != scope.GetId() {
|
||||
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
|
||||
func validateUpdateRequest(req *pbs.UpdateRoleRequest, s *scopes.ScopeInfo) error {
|
||||
return handlers.ValidateUpdateRequest(iam.RolePrefix, req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.GetItem().GetPrincipalIds() != nil {
|
||||
badFields["principal_ids"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
if req.GetItem().GetPrincipals() != nil {
|
||||
badFields["principals"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if req.GetItem().GetGrants() != nil {
|
||||
badFields["grants"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if req.GetItem().GetGrantStrings() != nil {
|
||||
badFields["grant_strings"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if req.GetItem().GetGrantScopeId() != nil && s.GetType() == scope.Project.String() {
|
||||
if req.GetItem().GetGrantScopeId().Value != s.GetId() {
|
||||
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
|
||||
}
|
||||
}
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteRoleRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.RolePrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateDeleteRequest(iam.RolePrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListRolesRequest) error {
|
||||
@@ -639,7 +586,7 @@ func validateListRequest(req *pbs.ListRolesRequest) error {
|
||||
|
||||
func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -661,7 +608,7 @@ func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
|
||||
|
||||
func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -680,7 +627,7 @@ func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error {
|
||||
|
||||
func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -697,7 +644,7 @@ func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) e
|
||||
|
||||
func validateAddRoleGrantsRequest(req *pbs.AddRoleGrantsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -714,7 +661,7 @@ func validateAddRoleGrantsRequest(req *pbs.AddRoleGrantsRequest) error {
|
||||
|
||||
func validateSetRoleGrantsRequest(req *pbs.SetRoleGrantsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -728,7 +675,7 @@ func validateSetRoleGrantsRequest(req *pbs.SetRoleGrantsRequest) error {
|
||||
|
||||
func validateRemoveRoleGrantsRequest(req *pbs.RemoveRoleGrantsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetRoleId(), iam.RolePrefix+"_") {
|
||||
if !handlers.ValidId(iam.RolePrefix, req.GetRoleId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
@@ -742,11 +689,3 @@ func validateRemoveRoleGrantsRequest(req *pbs.RemoveRoleGrantsRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
@@ -21,7 +19,6 @@ import (
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -261,80 +258,19 @@ func toProto(in *iam.User) *pb.User {
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetUserRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.UserPrefix+"_") {
|
||||
badFields["id"] = "Invalid formatted user id."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateGetRequest(iam.UserPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateUserRequest) error {
|
||||
badFields := map[string]string{}
|
||||
item := req.GetItem()
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
if item.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateUserRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.UserPrefix+"_") {
|
||||
badFields["user_id"] = "Improperly formatted path identifier."
|
||||
}
|
||||
if req.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update a user."
|
||||
}
|
||||
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if item.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if item.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if item.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
|
||||
return nil
|
||||
return handlers.ValidateUpdateRequest(iam.UserPrefix, req, req.GetItem(), handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteUserRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !validId(req.GetId(), iam.UserPrefix+"_") {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
return handlers.ValidateDeleteRequest(iam.UserPrefix, req, handlers.NoopValidatorFn)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListUsersRequest) error {
|
||||
@@ -344,11 +280,3 @@ func validateListRequest(req *pbs.ListUsersRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validId(id, prefix string) bool {
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes"
|
||||
"google.golang.org/genproto/protobuf/field_mask"
|
||||
)
|
||||
|
||||
type CustomValidatorFunc func() map[string]string
|
||||
|
||||
var NoopValidatorFn CustomValidatorFunc = func() map[string]string { return nil }
|
||||
|
||||
type ApiResource interface {
|
||||
GetId() string
|
||||
GetScope() *scopes.ScopeInfo
|
||||
GetName() *wrappers.StringValue
|
||||
GetDescription() *wrappers.StringValue
|
||||
GetCreatedTime() *timestamp.Timestamp
|
||||
GetUpdatedTime() *timestamp.Timestamp
|
||||
GetVersion() uint32
|
||||
}
|
||||
|
||||
func ValidateCreateRequest(i ApiResource, fn CustomValidatorFunc) error {
|
||||
badFields := map[string]string{}
|
||||
if i.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field."
|
||||
}
|
||||
if i.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field."
|
||||
}
|
||||
if i.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field."
|
||||
}
|
||||
if i.GetVersion() != 0 {
|
||||
badFields["version"] = "Cannot specify this field in a create request."
|
||||
}
|
||||
for k, v := range fn() {
|
||||
badFields[k] = v
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return InvalidArgumentErrorf("Argument errors found in the request.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateRequest interface {
|
||||
GetId() string
|
||||
GetUpdateMask() *field_mask.FieldMask
|
||||
}
|
||||
|
||||
func ValidateUpdateRequest(prefix string, r UpdateRequest, i ApiResource, fn CustomValidatorFunc) error {
|
||||
badFields := map[string]string{}
|
||||
if !ValidId(prefix, r.GetId()) {
|
||||
badFields["id"] = "Improperly formatted path identifier."
|
||||
}
|
||||
if r.GetUpdateMask() == nil {
|
||||
badFields["update_mask"] = "UpdateMask not provided but is required to update this resource."
|
||||
}
|
||||
|
||||
if i == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
// the mask will be marked as unset.
|
||||
return nil
|
||||
}
|
||||
if i.GetVersion() == 0 {
|
||||
badFields["version"] = "Existing resource version is required for an update."
|
||||
}
|
||||
if i.GetId() != "" {
|
||||
badFields["id"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if i.GetCreatedTime() != nil {
|
||||
badFields["created_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
if i.GetUpdatedTime() != nil {
|
||||
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
|
||||
}
|
||||
|
||||
for k, v := range fn() {
|
||||
badFields[k] = v
|
||||
}
|
||||
|
||||
if len(badFields) > 0 {
|
||||
return InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetRequest interface {
|
||||
GetId() string
|
||||
}
|
||||
|
||||
func ValidateGetRequest(prefix string, r GetRequest, fn CustomValidatorFunc) error {
|
||||
badFields := map[string]string{}
|
||||
if !ValidId(prefix, r.GetId()) {
|
||||
badFields["id"] = "Invalid formatted group id."
|
||||
}
|
||||
for k, v := range fn() {
|
||||
badFields[k] = v
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteRequest interface {
|
||||
GetId() string
|
||||
}
|
||||
|
||||
func ValidateDeleteRequest(prefix string, r DeleteRequest, fn CustomValidatorFunc) error {
|
||||
badFields := map[string]string{}
|
||||
if !ValidId(prefix, r.GetId()) {
|
||||
badFields["id"] = "Incorrectly formatted identifier."
|
||||
}
|
||||
for k, v := range fn() {
|
||||
badFields[k] = v
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
|
||||
func ValidId(prefix, id string) bool {
|
||||
prefix = prefix + "_"
|
||||
if !strings.HasPrefix(id, prefix) {
|
||||
return false
|
||||
}
|
||||
id = strings.TrimPrefix(id, prefix)
|
||||
return !reInvalidID.Match([]byte(id))
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/users"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/genproto/googleapis/rpc/errdetails"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func errorIncludesFields(t *testing.T, err error, wantFields []string) {
|
||||
t.Helper()
|
||||
s, ok := status.FromError(err)
|
||||
require.True(t, ok)
|
||||
require.Len(t, s.Details(), 1)
|
||||
rd, ok := s.Details()[0].(*errdetails.BadRequest)
|
||||
require.True(t, ok)
|
||||
var gotFields []string
|
||||
for _, d := range rd.FieldViolations {
|
||||
gotFields = append(gotFields, d.Field)
|
||||
}
|
||||
assert.ElementsMatch(t, gotFields, wantFields)
|
||||
}
|
||||
|
||||
// Throughout this test we will use the User requests, but we could use any request
|
||||
// message. User was picked arbitrarily.
|
||||
|
||||
func TestValidId(t *testing.T) {
|
||||
assert.True(t, ValidId("prefix", "prefix_somerandomid"))
|
||||
assert.True(t, ValidId("prefix", "prefix_short"))
|
||||
assert.True(t, ValidId("prefix", "prefix_thisisalongidentifierwhichstillworks"))
|
||||
|
||||
assert.False(t, ValidId("prefix", "prefixsomerandomid"))
|
||||
assert.False(t, ValidId("prefix", "prefix_this has spaces"))
|
||||
assert.False(t, ValidId("prefix", "prefix_includes-dash"))
|
||||
assert.False(t, ValidId("prefix", "prefix_other@strange!characters"))
|
||||
assert.False(t, ValidId("short", "prefix_short"))
|
||||
}
|
||||
|
||||
func TestValidateGetRequest(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
prefix string
|
||||
req GetRequest
|
||||
valFn CustomValidatorFunc
|
||||
badFields []string
|
||||
}{
|
||||
{
|
||||
name: "noopvalidator no error",
|
||||
prefix: "prefix",
|
||||
req: &pbs.GetUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
},
|
||||
{
|
||||
name: "noopvalidator bad prefix",
|
||||
prefix: "bad",
|
||||
req: &pbs.GetUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id"},
|
||||
},
|
||||
{
|
||||
name: "custom field error",
|
||||
prefix: "prefix",
|
||||
req: &pbs.GetUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"test"},
|
||||
},
|
||||
{
|
||||
name: "both custom error and prefix",
|
||||
prefix: "bad",
|
||||
req: &pbs.GetUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"id", "test"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ValidateGetRequest(tc.prefix, tc.req, tc.valFn)
|
||||
if len(tc.badFields) == 0 {
|
||||
if !assert.NoError(t, err) {
|
||||
errorIncludesFields(t, err, []string{})
|
||||
}
|
||||
return
|
||||
}
|
||||
errorIncludesFields(t, err, tc.badFields)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDeleteRequest(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
prefix string
|
||||
req DeleteRequest
|
||||
valFn CustomValidatorFunc
|
||||
badFields []string
|
||||
}{
|
||||
{
|
||||
name: "noopvalidator no error",
|
||||
prefix: "prefix",
|
||||
req: &pbs.DeleteUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
},
|
||||
{
|
||||
name: "noopvalidator bad prefix",
|
||||
prefix: "bad",
|
||||
req: &pbs.DeleteUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id"},
|
||||
},
|
||||
{
|
||||
name: "custom field error",
|
||||
prefix: "prefix",
|
||||
req: &pbs.DeleteUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"test"},
|
||||
},
|
||||
{
|
||||
name: "both custom error and prefix",
|
||||
prefix: "bad",
|
||||
req: &pbs.DeleteUserRequest{
|
||||
Id: "prefix_someidentifier",
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"id", "test"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ValidateDeleteRequest(tc.prefix, tc.req, tc.valFn)
|
||||
if len(tc.badFields) == 0 {
|
||||
if !assert.NoError(t, err) {
|
||||
errorIncludesFields(t, err, []string{})
|
||||
}
|
||||
return
|
||||
}
|
||||
errorIncludesFields(t, err, tc.badFields)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCreateRequest(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
item ApiResource
|
||||
valFn CustomValidatorFunc
|
||||
badFields []string
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
item: &pb.User{},
|
||||
valFn: NoopValidatorFn,
|
||||
},
|
||||
{
|
||||
name: "disallow set id",
|
||||
item: &pb.User{
|
||||
Id: "anything",
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id"},
|
||||
},
|
||||
{
|
||||
name: "disallow set created",
|
||||
item: &pb.User{
|
||||
CreatedTime: timestamppb.Now(),
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"created_time"},
|
||||
},
|
||||
{
|
||||
name: "disallow set updated",
|
||||
item: &pb.User{
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"updated_time"},
|
||||
},
|
||||
{
|
||||
name: "disallow set version",
|
||||
item: &pb.User{
|
||||
Version: 4,
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"version"},
|
||||
},
|
||||
{
|
||||
name: "custom validator error",
|
||||
item: &pb.User{},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"test"},
|
||||
},
|
||||
{
|
||||
name: "disallow several fields",
|
||||
item: &pb.User{
|
||||
Id: "anything",
|
||||
CreatedTime: timestamppb.Now(),
|
||||
Version: 4,
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{"test": "test"}
|
||||
},
|
||||
badFields: []string{"id", "created_time", "version", "test"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ValidateCreateRequest(tc.item, tc.valFn)
|
||||
if len(tc.badFields) == 0 {
|
||||
if !assert.NoError(t, err) {
|
||||
errorIncludesFields(t, err, []string{})
|
||||
}
|
||||
return
|
||||
}
|
||||
errorIncludesFields(t, err, tc.badFields)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUpdateRequest(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
prefix string
|
||||
req UpdateRequest
|
||||
item ApiResource
|
||||
valFn CustomValidatorFunc
|
||||
badFields []string
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
},
|
||||
{
|
||||
name: "missing mask",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"update_mask"},
|
||||
},
|
||||
{
|
||||
name: "bad id",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "mismatched_prefix",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id"},
|
||||
},
|
||||
{
|
||||
name: "missing version",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"version"},
|
||||
},
|
||||
{
|
||||
name: "bad create time",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
CreatedTime: timestamppb.Now(),
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"created_time"},
|
||||
},
|
||||
{
|
||||
name: "bad updated time",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"updated_time"},
|
||||
},
|
||||
{
|
||||
name: "bad defined id on item",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Id: "prefix_something",
|
||||
Version: 1,
|
||||
},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id"},
|
||||
},
|
||||
{
|
||||
name: "custom validator error",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{
|
||||
Id: "prefix_something",
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"anything"}},
|
||||
},
|
||||
item: &pb.User{
|
||||
Version: 1,
|
||||
},
|
||||
valFn: func() map[string]string {
|
||||
return map[string]string{
|
||||
"test": "test",
|
||||
}
|
||||
},
|
||||
badFields: []string{"test"},
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
prefix: "prefix",
|
||||
req: &pbs.UpdateUserRequest{},
|
||||
item: &pb.User{},
|
||||
valFn: NoopValidatorFn,
|
||||
badFields: []string{"id", "update_mask", "version"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ValidateUpdateRequest(tc.prefix, tc.req, tc.item, tc.valFn)
|
||||
if len(tc.badFields) == 0 {
|
||||
if !assert.NoError(t, err) {
|
||||
errorIncludesFields(t, err, []string{})
|
||||
}
|
||||
return
|
||||
}
|
||||
errorIncludesFields(t, err, tc.badFields)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user