Account API handler for CRDL operations (#228)

This commit is contained in:
Todd Knight authored and GitHub committed 2020-08-05 10:19:55 -07:00
1 parent 2ca7e0b88e
commit e5ec1f48b2
22 files changed
+3777 -91

No files matched your search

+61 -52
View File
@@ -11,6 +11,7 @@ package store
import (
proto "github.com/golang/protobuf/proto"
timestamp "github.com/hashicorp/watchtower/internal/db/timestamp"
_ "github.com/hashicorp/watchtower/internal/gen/controller/protooptions"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@@ -271,58 +272,66 @@ var file_controller_storage_auth_password_store_v1_password_proto_rawDesc = []by
0x72, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x03, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d,
0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a,
0x10, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x5f, 0x69,
0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x69, 0x6e, 0x5f, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18,
0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61,
0x6d, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f,
0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18,
0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0xb9, 0x02, 0x0a, 0x07, 0x41, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49,
0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b,
0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x4d,
0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
0x4e, 0x61, 0x6d, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74,
0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2f, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0xd1, 0x03, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12,
0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73,
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63,
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72,
0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b,
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19,
0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x61, 0x73,
0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x6e,
0x66, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x11, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x65,
0x6e, 0x67, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x11, 0x6d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65,
0x6e, 0x67, 0x74, 0x68, 0x22, 0xeb, 0x02, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a,
0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76,
0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a,
0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
0x28, 0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x24, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69,
0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74,
0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61,
0x6d, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68,
0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61,
0x75, 0x74, 0x68, 0x2f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2f, 0x73, 0x74, 0x6f,
0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
+266
View File
@@ -72,6 +72,171 @@
]
}
},
"/v1/scopes/*/auth-methods/{auth_method_id}/accounts": {
"get": {
"summary": "Lists all accounts in a specific auth method.",
"operationId": "AccountService_ListAccounts",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/controller.api.services.v1.ListAccountsResponse"
}
}
},
"parameters": [
{
"name": "auth_method_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "view",
"in": "query",
"required": false,
"type": "string"
}
],
"tags": [
"controller.api.services.v1.AccountService"
]
},
"post": {
"summary": "Creates a single account in the provided auth method.",
"operationId": "AccountService_CreateAccount",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"parameters": [
{
"name": "auth_method_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
],
"tags": [
"controller.api.services.v1.AccountService"
]
}
},
"/v1/scopes/*/auth-methods/{auth_method_id}/accounts/{id}": {
"get": {
"summary": "Gets a single Account",
"operationId": "AccountService_GetAccount",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"parameters": [
{
"name": "auth_method_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "view",
"in": "query",
"required": false,
"type": "string"
}
],
"tags": [
"controller.api.services.v1.AccountService"
]
},
"delete": {
"summary": "Deletes an account.",
"operationId": "AccountService_DeleteAccount",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/controller.api.services.v1.DeleteAccountResponse"
}
}
},
"parameters": [
{
"name": "auth_method_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"controller.api.services.v1.AccountService"
]
},
"patch": {
"summary": "Updates an account.",
"operationId": "AccountService_UpdateAccount",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"parameters": [
{
"name": "auth_method_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
],
"tags": [
"controller.api.services.v1.AccountService"
]
}
},
"/v1/scopes/*/auth-methods/{auth_method_id}:authenticate": {
"post": {
"summary": "Authenticate a user to an scope and retrieve an authentication token.",
@@ -1506,6 +1671,60 @@
}
},
"definitions": {
"controller.api.resources.auth.v1.Account": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the Account\nOutput only.",
"readOnly": true
},
"scope": {
"$ref": "#/definitions/controller.api.resources.scopes.v1.ScopeInfo",
"description": "Scope information for this resource\nOutput only.",
"readOnly": true
},
"auth_method_id": {
"type": "string",
"description": "The auth method this account is created for.\nOutput only.",
"readOnly": true
},
"name": {
"type": "string",
"title": "Optional name for identification purposes"
},
"description": {
"type": "string",
"title": "Optional user-set descripton for identification purposes"
},
"created_time": {
"type": "string",
"format": "date-time",
"description": "The time this resource was created\nOutput only.",
"readOnly": true
},
"updated_time": {
"type": "string",
"format": "date-time",
"description": "The time this resource was last updated.\nOutput only.",
"readOnly": true
},
"disabled": {
"type": "boolean",
"format": "boolean",
"title": "Whether the resource is disabled"
},
"type": {
"type": "string",
"description": "The type of this account. Possible values are: \"password\", \"oidc\"."
},
"attributes": {
"type": "object",
"description": "The attributes that are applicable for the specific Account type."
}
},
"title": "Account contains all fields related to an auth Account resource"
},
"controller.api.resources.authtokens.v1.AuthToken": {
"type": "object",
"properties": {
@@ -2168,6 +2387,17 @@
}
}
},
"controller.api.services.v1.CreateAccountResponse": {
"type": "object",
"properties": {
"uri": {
"type": "string"
},
"item": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"controller.api.services.v1.CreateGroupResponse": {
"type": "object",
"properties": {
@@ -2245,6 +2475,15 @@
}
}
},
"controller.api.services.v1.DeleteAccountResponse": {
"type": "object",
"properties": {
"existed": {
"type": "boolean",
"format": "boolean"
}
}
},
"controller.api.services.v1.DeleteAuthTokenResponse": {
"type": "object",
"properties": {
@@ -2317,6 +2556,14 @@
}
}
},
"controller.api.services.v1.GetAccountResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"controller.api.services.v1.GetAuthTokenResponse": {
"type": "object",
"properties": {
@@ -2381,6 +2628,17 @@
}
}
},
"controller.api.services.v1.ListAccountsResponse": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
}
},
"controller.api.services.v1.ListAuthTokensResponse": {
"type": "object",
"properties": {
@@ -2634,6 +2892,14 @@
}
}
},
"controller.api.services.v1.UpdateAccountResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.auth.v1.Account"
}
}
},
"controller.api.services.v1.UpdateGroupResponse": {
"type": "object",
"properties": {
@@ -0,0 +1,382 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: controller/api/resources/auth/v1/account.proto
package auth
import (
proto "github.com/golang/protobuf/proto"
_struct "github.com/golang/protobuf/ptypes/struct"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
wrappers "github.com/golang/protobuf/ptypes/wrappers"
scopes "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
_ "github.com/hashicorp/watchtower/internal/gen/controller/protooptions"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
// Account contains all fields related to an auth Account resource
type Account struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The ID of the Account
// Output only.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// Scope information for this resource
// Output only.
Scope *scopes.ScopeInfo `protobuf:"bytes,2,opt,name=scope,proto3" json:"scope,omitempty"`
// The auth method this account is created for.
// Output only.
AuthMethodId string `protobuf:"bytes,3,opt,name=auth_method_id,proto3" json:"auth_method_id,omitempty"`
// Optional name for identification purposes
Name *wrappers.StringValue `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
// Optional user-set descripton for identification purposes
Description *wrappers.StringValue `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
// The time this resource was created
// Output only.
CreatedTime *timestamp.Timestamp `protobuf:"bytes,6,opt,name=created_time,proto3" json:"created_time,omitempty"`
// The time this resource was last updated.
// Output only.
UpdatedTime *timestamp.Timestamp `protobuf:"bytes,7,opt,name=updated_time,proto3" json:"updated_time,omitempty"`
// Whether the resource is disabled
Disabled *wrappers.BoolValue `protobuf:"bytes,8,opt,name=disabled,proto3" json:"disabled,omitempty"`
// The type of this account. Possible values are: "password", "oidc".
Type string `protobuf:"bytes,9,opt,name=type,proto3" json:"type,omitempty"`
// The attributes that are applicable for the specific Account type.
Attributes *_struct.Struct `protobuf:"bytes,10,opt,name=attributes,proto3" json:"attributes,omitempty"`
}
func (x *Account) Reset() {
*x = Account{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_auth_v1_account_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Account) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_auth_v1_account_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
return file_controller_api_resources_auth_v1_account_proto_rawDescGZIP(), []int{0}
}
func (x *Account) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Account) GetScope() *scopes.ScopeInfo {
if x != nil {
return x.Scope
}
return nil
}
func (x *Account) GetAuthMethodId() string {
if x != nil {
return x.AuthMethodId
}
return ""
}
func (x *Account) GetName() *wrappers.StringValue {
if x != nil {
return x.Name
}
return nil
}
func (x *Account) GetDescription() *wrappers.StringValue {
if x != nil {
return x.Description
}
return nil
}
func (x *Account) GetCreatedTime() *timestamp.Timestamp {
if x != nil {
return x.CreatedTime
}
return nil
}
func (x *Account) GetUpdatedTime() *timestamp.Timestamp {
if x != nil {
return x.UpdatedTime
}
return nil
}
func (x *Account) GetDisabled() *wrappers.BoolValue {
if x != nil {
return x.Disabled
}
return nil
}
func (x *Account) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *Account) GetAttributes() *_struct.Struct {
if x != nil {
return x.Attributes
}
return nil
}
type PasswordAccountAttributes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The username of this account. This is unique per auth method.
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
// The password for this account.
Password *wrappers.StringValue `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *PasswordAccountAttributes) Reset() {
*x = PasswordAccountAttributes{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_auth_v1_account_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PasswordAccountAttributes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PasswordAccountAttributes) ProtoMessage() {}
func (x *PasswordAccountAttributes) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_auth_v1_account_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PasswordAccountAttributes.ProtoReflect.Descriptor instead.
func (*PasswordAccountAttributes) Descriptor() ([]byte, []int) {
return file_controller_api_resources_auth_v1_account_proto_rawDescGZIP(), []int{1}
}
func (x *PasswordAccountAttributes) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *PasswordAccountAttributes) GetPassword() *wrappers.StringValue {
if x != nil {
return x.Password
}
return nil
}
var File_controller_api_resources_auth_v1_account_proto protoreflect.FileDescriptor
var file_controller_api_resources_auth_v1_account_proto_rawDesc = []byte{
0x0a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x63, 0x6f, 0x70,
0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75,
0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f,
0x6d, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xaf, 0x04, 0x0a, 0x07,
0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0e,
0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f,
0x64, 0x5f, 0x69, 0x64, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x5e, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x1e, 0xc2, 0xdd, 0x29,
0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b,
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61,
0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f,
0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63,
0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x71, 0x0a,
0x19, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f,
0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x3b, 0x61,
0x75, 0x74, 0x68, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_controller_api_resources_auth_v1_account_proto_rawDescOnce sync.Once
file_controller_api_resources_auth_v1_account_proto_rawDescData = file_controller_api_resources_auth_v1_account_proto_rawDesc
)
func file_controller_api_resources_auth_v1_account_proto_rawDescGZIP() []byte {
file_controller_api_resources_auth_v1_account_proto_rawDescOnce.Do(func() {
file_controller_api_resources_auth_v1_account_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_api_resources_auth_v1_account_proto_rawDescData)
})
return file_controller_api_resources_auth_v1_account_proto_rawDescData
}
var file_controller_api_resources_auth_v1_account_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_controller_api_resources_auth_v1_account_proto_goTypes = []interface{}{
(*Account)(nil), // 0: controller.api.resources.auth.v1.Account
(*PasswordAccountAttributes)(nil), // 1: controller.api.resources.auth.v1.PasswordAccountAttributes
(*scopes.ScopeInfo)(nil), // 2: controller.api.resources.scopes.v1.ScopeInfo
(*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue
(*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp
(*wrappers.BoolValue)(nil), // 5: google.protobuf.BoolValue
(*_struct.Struct)(nil), // 6: google.protobuf.Struct
}
var file_controller_api_resources_auth_v1_account_proto_depIdxs = []int32{
2, // 0: controller.api.resources.auth.v1.Account.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
3, // 1: controller.api.resources.auth.v1.Account.name:type_name -> google.protobuf.StringValue
3, // 2: controller.api.resources.auth.v1.Account.description:type_name -> google.protobuf.StringValue
4, // 3: controller.api.resources.auth.v1.Account.created_time:type_name -> google.protobuf.Timestamp
4, // 4: controller.api.resources.auth.v1.Account.updated_time:type_name -> google.protobuf.Timestamp
5, // 5: controller.api.resources.auth.v1.Account.disabled:type_name -> google.protobuf.BoolValue
6, // 6: controller.api.resources.auth.v1.Account.attributes:type_name -> google.protobuf.Struct
3, // 7: controller.api.resources.auth.v1.PasswordAccountAttributes.password:type_name -> google.protobuf.StringValue
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_controller_api_resources_auth_v1_account_proto_init() }
func file_controller_api_resources_auth_v1_account_proto_init() {
if File_controller_api_resources_auth_v1_account_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_controller_api_resources_auth_v1_account_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Account); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_resources_auth_v1_account_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PasswordAccountAttributes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_api_resources_auth_v1_account_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_controller_api_resources_auth_v1_account_proto_goTypes,
DependencyIndexes: file_controller_api_resources_auth_v1_account_proto_depIdxs,
MessageInfos: file_controller_api_resources_auth_v1_account_proto_msgTypes,
}.Build()
File_controller_api_resources_auth_v1_account_proto = out.File
file_controller_api_resources_auth_v1_account_proto_rawDesc = nil
file_controller_api_resources_auth_v1_account_proto_goTypes = nil
file_controller_api_resources_auth_v1_account_proto_depIdxs = nil
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,766 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: controller/api/services/v1/authaccount_service.proto
/*
Package services is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package services
import (
"context"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var (
filter_AccountService_GetAccount_0 = &utilities.DoubleArray{Encoding: map[string]int{"auth_method_id": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
)
func request_AccountService_GetAccount_0(ctx context.Context, marshaler runtime.Marshaler, client AccountServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetAccountRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_GetAccount_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.GetAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AccountService_GetAccount_0(ctx context.Context, marshaler runtime.Marshaler, server AccountServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetAccountRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_GetAccount_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.GetAccount(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_AccountService_ListAccounts_0 = &utilities.DoubleArray{Encoding: map[string]int{"auth_method_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_AccountService_ListAccounts_0(ctx context.Context, marshaler runtime.Marshaler, client AccountServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListAccountsRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_ListAccounts_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListAccounts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AccountService_ListAccounts_0(ctx context.Context, marshaler runtime.Marshaler, server AccountServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListAccountsRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_ListAccounts_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListAccounts(ctx, &protoReq)
return msg, metadata, err
}
func request_AccountService_CreateAccount_0(ctx context.Context, marshaler runtime.Marshaler, client AccountServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateAccountRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
msg, err := client.CreateAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AccountService_CreateAccount_0(ctx context.Context, marshaler runtime.Marshaler, server AccountServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateAccountRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
msg, err := server.CreateAccount(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_AccountService_UpdateAccount_0 = &utilities.DoubleArray{Encoding: map[string]int{"item": 0, "auth_method_id": 1, "id": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}}
)
func request_AccountService_UpdateAccount_0(ctx context.Context, marshaler runtime.Marshaler, client AccountServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UpdateAccountRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_UpdateAccount_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdateAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AccountService_UpdateAccount_0(ctx context.Context, marshaler runtime.Marshaler, server AccountServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UpdateAccountRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AccountService_UpdateAccount_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdateAccount(ctx, &protoReq)
return msg, metadata, err
}
func request_AccountService_DeleteAccount_0(ctx context.Context, marshaler runtime.Marshaler, client AccountServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteAccountRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.DeleteAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AccountService_DeleteAccount_0(ctx context.Context, marshaler runtime.Marshaler, server AccountServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteAccountRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.DeleteAccount(ctx, &protoReq)
return msg, metadata, err
}
// RegisterAccountServiceHandlerServer registers the http handlers for service AccountService to "mux".
// UnaryRPC :call AccountServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
func RegisterAccountServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AccountServiceServer) error {
mux.Handle("GET", pattern_AccountService_GetAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AccountService/GetAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AccountService_GetAccount_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_GetAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_GetAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AccountService_ListAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AccountService/ListAccounts")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AccountService_ListAccounts_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_ListAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AccountService_CreateAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AccountService/CreateAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AccountService_CreateAccount_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_CreateAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_CreateAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("PATCH", pattern_AccountService_UpdateAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AccountService/UpdateAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AccountService_UpdateAccount_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_UpdateAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_UpdateAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_AccountService_DeleteAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AccountService/DeleteAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AccountService_DeleteAccount_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_DeleteAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterAccountServiceHandlerFromEndpoint is same as RegisterAccountServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterAccountServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterAccountServiceHandler(ctx, mux, conn)
}
// RegisterAccountServiceHandler registers the http handlers for service AccountService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterAccountServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterAccountServiceHandlerClient(ctx, mux, NewAccountServiceClient(conn))
}
// RegisterAccountServiceHandlerClient registers the http handlers for service AccountService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AccountServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AccountServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "AccountServiceClient" to call the correct interceptors.
func RegisterAccountServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AccountServiceClient) error {
mux.Handle("GET", pattern_AccountService_GetAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AccountService/GetAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AccountService_GetAccount_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_GetAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_GetAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_AccountService_ListAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AccountService/ListAccounts")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AccountService_ListAccounts_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_ListAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AccountService_CreateAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AccountService/CreateAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AccountService_CreateAccount_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_CreateAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_CreateAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("PATCH", pattern_AccountService_UpdateAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AccountService/UpdateAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AccountService_UpdateAccount_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_UpdateAccount_0(ctx, mux, outboundMarshaler, w, req, response_AccountService_UpdateAccount_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_AccountService_DeleteAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AccountService/DeleteAccount")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AccountService_DeleteAccount_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AccountService_DeleteAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
type response_AccountService_GetAccount_0 struct {
proto.Message
}
func (m response_AccountService_GetAccount_0) XXX_ResponseBody() interface{} {
response := m.Message.(*GetAccountResponse)
return response.Item
}
type response_AccountService_CreateAccount_0 struct {
proto.Message
}
func (m response_AccountService_CreateAccount_0) XXX_ResponseBody() interface{} {
response := m.Message.(*CreateAccountResponse)
return response.Item
}
type response_AccountService_UpdateAccount_0 struct {
proto.Message
}
func (m response_AccountService_UpdateAccount_0) XXX_ResponseBody() interface{} {
response := m.Message.(*UpdateAccountResponse)
return response.Item
}
var (
pattern_AccountService_GetAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "scopes", "auth-methods", "auth_method_id", "accounts", "id"}, ""))
pattern_AccountService_ListAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"v1", "scopes", "auth-methods", "auth_method_id", "accounts"}, ""))
pattern_AccountService_CreateAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"v1", "scopes", "auth-methods", "auth_method_id", "accounts"}, ""))
pattern_AccountService_UpdateAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "scopes", "auth-methods", "auth_method_id", "accounts", "id"}, ""))
pattern_AccountService_DeleteAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "scopes", "auth-methods", "auth_method_id", "accounts", "id"}, ""))
)
var (
forward_AccountService_GetAccount_0 = runtime.ForwardResponseMessage
forward_AccountService_ListAccounts_0 = runtime.ForwardResponseMessage
forward_AccountService_CreateAccount_0 = runtime.ForwardResponseMessage
forward_AccountService_UpdateAccount_0 = runtime.ForwardResponseMessage
forward_AccountService_DeleteAccount_0 = runtime.ForwardResponseMessage
)
@@ -0,0 +1,56 @@
syntax = "proto3";
package controller.api.resources.auth.v1;
option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/auth;auth";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";
import "controller/api/resources/scopes/v1/scope.proto";
import "controller/custom_options/v1/masks.proto";
// Account contains all fields related to an auth Account resource
message Account {
// The ID of the Account
// Output only.
string id = 1;
// Scope information for this resource
// Output only.
resources.scopes.v1.ScopeInfo scope = 2;
// The auth method this account is created for.
// Output only.
string auth_method_id = 3 [json_name="auth_method_id"];
// Optional name for identification purposes
google.protobuf.StringValue name = 4 [(custom_options.v1.mask_mapping) = {this:"name" that: "name"}];
// Optional user-set descripton for identification purposes
google.protobuf.StringValue description = 5 [(custom_options.v1.mask_mapping) = {this:"description" that: "description"}];
// The time this resource was created
// Output only.
google.protobuf.Timestamp created_time = 6 [json_name="created_time"];
// The time this resource was last updated.
// Output only.
google.protobuf.Timestamp updated_time = 7 [json_name="updated_time"];
// Whether the resource is disabled
google.protobuf.BoolValue disabled = 8;
// The type of this account. Possible values are: "password", "oidc".
string type = 9;
// The attributes that are applicable for the specific Account type.
google.protobuf.Struct attributes = 10;
}
message PasswordAccountAttributes {
// The username of this account. This is unique per auth method.
string username = 1;
// The password for this account.
google.protobuf.StringValue password = 2;
}
@@ -0,0 +1,139 @@
syntax = "proto3";
package controller.api.services.v1;
option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api/services;services";
import "protoc-gen-openapiv2/options/annotations.proto";
import "google/api/annotations.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/wrappers.proto";
import "controller/api/resources/auth/v1/account.proto";
service AccountService {
// GetAccount returns a stored Account if present. The provided request must
// include the scope for the group being retrieved. If any of those ids are
// missing, malformed or reference a non existing resource an error is
// returned.
rpc GetAccount(GetAccountRequest) returns (GetAccountResponse) {
option (google.api.http) = {
get: "/v1/scopes/*/auth-methods/{auth_method_id}/accounts/{id}"
response_body: "item"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Gets a single Account"
};
}
// ListAccounts returns a list of stored accounts which exist inside the
// auth method referenced inside the request. The request must include the
// auth method for the account being retrieved. If the auth method is missing,
// malformed, or references a non-existing auth method, an error is returned.
rpc ListAccounts(ListAccountsRequest) returns (ListAccountsResponse) {
option (google.api.http) = {
get: "/v1/scopes/*/auth-methods/{auth_method_id}/accounts"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Lists all accounts in a specific auth method."
};
}
// CreateAccount creates and stores an account in watchtower. The provided
// request must include the auth method id in which the account will be created.
// If the auth method id is missing, malformed or references a non existing
// auth method, an error is returned. If a name is provided that is in
// use in another account in the same auth method, an error is returned.
rpc CreateAccount(CreateAccountRequest) returns (CreateAccountResponse) {
option (google.api.http) = {
post: "/v1/scopes/*/auth-methods/{auth_method_id}/accounts"
body: "item"
response_body: "item"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Creates a single account in the provided auth method."
};
}
// UpdateAccount updates an existing account in watchtower. The provided account
// must not have any read only fields set. The update mask must be included in
// the request and contain at least 1 mutable field. To unset a field's value,
// include the field in the update mask and don't set it in the provided
// account. An error is returned if either the auth method or account ids are
// missing or reference a non-existing resource. An error is also returned if the
// request attempts to update the name to one that is already in use in this
// auth method.
rpc UpdateAccount(UpdateAccountRequest) returns (UpdateAccountResponse) {
option (google.api.http) = {
patch: "/v1/scopes/*/auth-methods/{auth_method_id}/accounts/{id}"
body: "item"
response_body: "item"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Updates an account."
};
}
// DeleteAccount removes an account from Watchtower. If the provided auth mehtod
// or account ids are malformed or not provided an error is returned. No error is
// returned if either ids reference resources that do not exist as the
// response itself specifies if the resource existed before the DeleteAccount
// request was received.
rpc DeleteAccount(DeleteAccountRequest) returns (DeleteAccountResponse) {
option (google.api.http) = {
delete: "/v1/scopes/*/auth-methods/{auth_method_id}/accounts/{id}"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Deletes an account."
};
}
}
message GetAccountRequest {
string auth_method_id = 1;
string id = 2;
string view = 3;
}
message GetAccountResponse {
resources.auth.v1.Account item = 1;
}
message ListAccountsRequest {
string auth_method_id = 1;
string view = 2;
}
message ListAccountsResponse {
repeated resources.auth.v1.Account items = 1;
}
message CreateAccountRequest {
string auth_method_id = 1;
resources.auth.v1.Account item = 2;
}
message CreateAccountResponse {
string uri = 1;
resources.auth.v1.Account item = 2;
}
message UpdateAccountRequest {
string auth_method_id = 1;
string id = 2;
resources.auth.v1.Account item = 3;
google.protobuf.FieldMask update_mask = 4;
}
message UpdateAccountResponse {
resources.auth.v1.Account item = 1;
}
message DeleteAccountRequest {
string auth_method_id = 1;
string id = 2;
}
message DeleteAccountResponse {
bool existed = 1;
}
@@ -5,6 +5,7 @@ package controller.storage.auth.password.store.v1;
option go_package = "github.com/hashicorp/watchtower/internal/auth/password/store;store";
import "controller/storage/timestamp/v1/timestamp.proto";
import "controller/custom_options/v1/masks.proto";
message AuthMethod {
// @inject_tag: `gorm:"primary_key"`
@@ -20,11 +21,11 @@ message AuthMethod {
// name is optional. If set, it must be unique within scope_id.
// @inject_tag: `gorm:"default:null"`
string name = 4;
string name = 4 [(custom_options.v1.mask_mapping) = {this:"name" that: "name"}];
// description is optional.
// @inject_tag: `gorm:"default:null"`
string description = 5;
string description = 5 [(custom_options.v1.mask_mapping) = {this:"description" that: "description"}];
// The scope_id of the owning scope. Must be set.
// @inject_tag: `gorm:"not_null"`
@@ -54,11 +55,11 @@ message Account {
// name is optional. If set, it must be unique within scope_id.
// @inject_tag: `gorm:"default:null"`
string name = 4;
string name = 4 [(custom_options.v1.mask_mapping) = {this:"name" that: "name"}];
// description is optional.
// @inject_tag: `gorm:"default:null"`
string description = 5;
string description = 5 [(custom_options.v1.mask_mapping) = {this:"description" that: "description"}];
// @inject_tag: `gorm:"not_null"`
string auth_method_id = 6;
+5 -3
View File
@@ -1,13 +1,15 @@
package common
import (
"github.com/hashicorp/watchtower/internal/auth/password"
"github.com/hashicorp/watchtower/internal/authtoken"
"github.com/hashicorp/watchtower/internal/host/static"
"github.com/hashicorp/watchtower/internal/iam"
)
type (
IamRepoFactory func() (*iam.Repository, error)
StaticRepoFactory func() (*static.Repository, error)
AuthTokenRepoFactory func() (*authtoken.Repository, error)
IamRepoFactory func() (*iam.Repository, error)
StaticRepoFactory func() (*static.Repository, error)
AuthTokenRepoFactory func() (*authtoken.Repository, error)
PasswordAuthRepoFactory func() (*password.Repository, error)
)
@@ -7,6 +7,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/mlock"
"github.com/hashicorp/watchtower/internal/auth/password"
"github.com/hashicorp/watchtower/internal/authtoken"
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/host/static"
@@ -25,6 +26,8 @@ type Controller struct {
IamRepoFn common.IamRepoFactory
StaticHostRepoFn common.StaticRepoFactory
AuthTokenRepoFn common.AuthTokenRepoFactory
PasswordAuthRepoFn common.PasswordAuthRepoFactory
}
func New(conf *Config) (*Controller, error) {
@@ -66,6 +69,9 @@ func New(conf *Config) (*Controller, error) {
c.AuthTokenRepoFn = func() (*authtoken.Repository, error) {
return authtoken.NewRepository(dbase, dbase, c.conf.ControllerKMS)
}
c.PasswordAuthRepoFn = func() (*password.Repository, error) {
return password.NewRepository(dbase, dbase, c.conf.ControllerKMS)
}
return c, nil
}
+8
View File
@@ -16,6 +16,7 @@ import (
"github.com/hashicorp/watchtower/globals"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/accounts"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/authenticate"
@@ -80,6 +81,13 @@ func handleGrpcGateway(c *Controller) (http.Handler, error) {
if err := services.RegisterHostCatalogServiceHandlerServer(ctx, mux, hcs); err != nil {
return nil, fmt.Errorf("failed to register host catalog service handler: %w", err)
}
accts, err := accounts.NewService(c.logger, c.PasswordAuthRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create account handler service: %w", err)
}
if err := services.RegisterAccountServiceHandlerServer(ctx, mux, accts); err != nil {
return nil, fmt.Errorf("failed to register account service handler: %w", err)
}
auths, err := authenticate.NewService(c.IamRepoFn, c.AuthTokenRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create authentication handler service: %w", err)
@@ -46,6 +46,8 @@ func TestHandleImplementedPaths(t *testing.T) {
"v1/scopes/someid",
"v1/scopes/someid/auth-tokens",
"v1/scopes/someid/auth-tokens/someid",
"v1/scopes/someid/auth-methods/someid/accounts",
"v1/scopes/someid/auth-methods/someid/accounts/someid",
"v1/scopes/someid/groups",
"v1/scopes/someid/groups/someid",
"v1/scopes/someid/host-catalogs",
@@ -61,6 +63,7 @@ func TestHandleImplementedPaths(t *testing.T) {
"v1/scopes/someid/groups",
"v1/scopes/someid/roles",
"v1/scopes/someid/users",
"v1/scopes/someid/auth-methods/someid/accounts",
// custom methods
"v1/scopes/someid/auth-methods/someid:authenticate",
@@ -80,6 +83,7 @@ func TestHandleImplementedPaths(t *testing.T) {
"v1/scopes/someid/roles/someid",
"v1/scopes/someid/groups/someid",
"v1/scopes/someid/auth-tokens/someid",
"v1/scopes/someid/auth-methods/someid/accounts/someid",
},
"PATCH": {
"v1/scopes/someid",
@@ -0,0 +1,314 @@
package accounts
import (
"context"
"errors"
"fmt"
"regexp"
"strings"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/auth/password"
"github.com/hashicorp/watchtower/internal/auth/password/store"
"github.com/hashicorp/watchtower/internal/db"
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/auth"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
)
var (
maskManager handlers.MaskManager
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
)
func init() {
var err error
if maskManager, err = handlers.NewMaskManager(&pb.Account{}, &store.Account{}); err != nil {
panic(err)
}
}
// Service handles request as described by the pbs.AccountServiceServer interface.
type Service struct {
repoFn func() (*password.Repository, error)
log hclog.Logger
}
// NewService returns a user service which handles user related requests to watchtower.
func NewService(log hclog.Logger, repo func() (*password.Repository, error)) (Service, error) {
if repo == nil {
return Service{}, fmt.Errorf("nil password repository provided")
}
return Service{log: log, repoFn: repo}, nil
}
var _ pbs.AccountServiceServer = Service{}
// TODO(ICU-407): Validate that the provided auth method and account are in the provided scope.
// ListAccounts implements the interface pbs.AccountServiceServer.
func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest) (*pbs.ListAccountsResponse, error) {
authResults := auth.Verify(ctx)
if !authResults.Valid {
return nil, handlers.ForbiddenError()
}
if err := validateListRequest(req); err != nil {
return nil, err
}
ul, err := s.listFromRepo(ctx, req.GetAuthMethodId())
if err != nil {
return nil, err
}
for _, item := range ul {
item.Scope = authResults.Scope
}
return &pbs.ListAccountsResponse{Items: ul}, nil
}
// GetAccounts implements the interface pbs.AccountServiceServer.
func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*pbs.GetAccountResponse, error) {
authResults := auth.Verify(ctx)
if !authResults.Valid {
return nil, handlers.ForbiddenError()
}
if err := validateGetRequest(req); err != nil {
return nil, err
}
u, err := s.getFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
}
u.Scope = authResults.Scope
return &pbs.GetAccountResponse{Item: u}, nil
}
// CreateAccount implements the interface pbs.AccountServiceServer.
func (s Service) CreateAccount(ctx context.Context, req *pbs.CreateAccountRequest) (*pbs.CreateAccountResponse, error) {
authResults := auth.Verify(ctx)
if !authResults.Valid {
return nil, handlers.ForbiddenError()
}
if err := validateCreateRequest(req); err != nil {
return nil, err
}
u, err := s.createInRepo(ctx, req.GetAuthMethodId(), req.GetItem())
if err != nil {
return nil, err
}
u.Scope = authResults.Scope
return &pbs.CreateAccountResponse{Item: u, Uri: fmt.Sprintf("scopes/%s/auth-methods/%s/accounts/%s", authResults.Scope.GetId(), u.GetAuthMethodId(), u.GetId())}, nil
}
// UpdateAccount implements the interface pbs.AccountServiceServer.
func (s Service) UpdateAccount(ctx context.Context, req *pbs.UpdateAccountRequest) (*pbs.UpdateAccountResponse, error) {
panic("UpdateAccount is not implemented.")
}
// DeleteAccount implements the interface pbs.AccountServiceServer.
func (s Service) DeleteAccount(ctx context.Context, req *pbs.DeleteAccountRequest) (*pbs.DeleteAccountResponse, error) {
authResults := auth.Verify(ctx)
if !authResults.Valid {
return nil, handlers.ForbiddenError()
}
if err := validateDeleteRequest(req); err != nil {
return nil, err
}
existed, err := s.deleteFromRepo(ctx, req.GetId())
if err != nil {
return nil, err
}
return &pbs.DeleteAccountResponse{Existed: existed}, nil
}
func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Account, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
u, err := repo.LookupAccount(ctx, id)
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, handlers.NotFoundErrorf("Account %q doesn't exist.", id)
}
return nil, err
}
if u == nil {
return nil, handlers.NotFoundErrorf("Account %q doesn't exist.", id)
}
return s.toProto(u), nil
}
func (s Service) createInRepo(ctx context.Context, authMethodId string, item *pb.Account) (*pb.Account, error) {
pwAttrs := &pb.PasswordAccountAttributes{}
if err := handlers.StructToProto(item.GetAttributes(), pwAttrs); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Provided attributes don't match expected format.")
}
var opts []password.Option
if item.GetName() != nil {
opts = append(opts, password.WithName(item.GetName().GetValue()))
}
if item.GetDescription() != nil {
opts = append(opts, password.WithDescription(item.GetDescription().GetValue()))
}
a, err := password.NewAccount(authMethodId, pwAttrs.GetUsername(), opts...)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to build user for creation: %v.", err)
}
repo, err := s.repoFn()
if err != nil {
return nil, err
}
out, err := repo.CreateAccount(ctx, a)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to create user: %v.", err)
}
if out == nil {
return nil, status.Error(codes.Internal, "Unable to create user but no error returned from repository.")
}
return s.toProto(out), nil
}
func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) {
repo, err := s.repoFn()
if err != nil {
return false, err
}
rows, err := repo.DeleteAccount(ctx, id)
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return false, nil
}
return false, status.Errorf(codes.Internal, "Unable to delete user: %v.", err)
}
return rows > 0, nil
}
func (s Service) listFromRepo(ctx context.Context, authMethodId string) ([]*pb.Account, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
ul, err := repo.ListAccounts(ctx, authMethodId)
if err != nil {
return nil, err
}
var outUl []*pb.Account
for _, u := range ul {
outUl = append(outUl, s.toProto(u))
}
return outUl, nil
}
func (s Service) toProto(in *password.Account) *pb.Account {
out := pb.Account{
Id: in.GetPublicId(),
CreatedTime: in.GetCreateTime().GetTimestamp(),
UpdatedTime: in.GetUpdateTime().GetTimestamp(),
AuthMethodId: in.GetAuthMethodId(),
Type: "password",
}
if in.GetDescription() != "" {
out.Description = &wrapperspb.StringValue{Value: in.GetDescription()}
}
if in.GetName() != "" {
out.Name = &wrapperspb.StringValue{Value: in.GetName()}
}
if st, err := handlers.ProtoToStruct(&pb.PasswordAccountAttributes{Username: in.GetUserName()}); err == nil {
out.Attributes = st
} else {
s.log.Error("failed converting account attribute to struct", "error", err)
}
return &out
}
// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce
// requirements on the structure of the request. They verify that:
// * The path passed in is correctly formatted
// * 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
}
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.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 item.GetType() {
case "password":
pwAttrs := &pb.PasswordAccountAttributes{}
if err := handlers.StructToProto(item.GetAttributes(), pwAttrs); err != nil {
badFields["attributes"] = "Attribute fields do not match the expected format."
}
if pwAttrs.GetUsername() == "" {
badFields["username"] = "This is a required field for this type."
}
default:
badFields["type"] = "This is a required field."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
}
return nil
}
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
}
func validateListRequest(req *pbs.ListAccountsRequest) error {
badFields := map[string]string{}
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
}
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,435 @@
package accounts_test
import (
"fmt"
"strings"
"testing"
"github.com/golang/protobuf/ptypes"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/auth/password"
"github.com/hashicorp/watchtower/internal/authtoken"
"github.com/hashicorp/watchtower/internal/db"
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/auth"
"github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/iam"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/accounts"
"github.com/hashicorp/watchtower/internal/types/scope"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
func TestGet(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, wrap)
}
s, err := accounts.NewService(hclog.L(), repoFn)
require.NoError(t, err, "Couldn't create new auth token service.")
org, _ := iam.TestScopes(t, conn)
am := password.TestAuthMethods(t, conn, org.GetPublicId(), 1)[0]
aa := password.TestAccounts(t, conn, am.GetPublicId(), 1)[0]
wireAccount := pb.Account{
Id: aa.GetPublicId(),
AuthMethodId: aa.GetAuthMethodId(),
CreatedTime: aa.GetCreateTime().GetTimestamp(),
UpdatedTime: aa.GetUpdateTime().GetTimestamp(),
Scope: &scopes.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()},
Type: "password",
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"username": structpb.NewStringValue(aa.GetUserName())}},
}
cases := []struct {
name string
req *pbs.GetAccountRequest
res *pbs.GetAccountResponse
errCode codes.Code
}{
{
name: "Get an existing account",
req: &pbs.GetAccountRequest{AuthMethodId: wireAccount.GetAuthMethodId(), Id: wireAccount.GetId()},
res: &pbs.GetAccountResponse{Item: &wireAccount},
errCode: codes.OK,
},
{
name: "Get a non existing account",
req: &pbs.GetAccountRequest{AuthMethodId: wireAccount.GetAuthMethodId(), Id: password.AccountPrefix + "_DoesntExis"},
res: nil,
errCode: codes.NotFound,
},
{
name: "Wrong id prefix",
req: &pbs.GetAccountRequest{AuthMethodId: wireAccount.GetAuthMethodId(), Id: "j_1234567890"},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "space in id",
req: &pbs.GetAccountRequest{AuthMethodId: wireAccount.GetAuthMethodId(), Id: authtoken.AuthTokenPrefix + "_1 23456789"},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.GetAccount(auth.DisabledAuthTestContext(auth.WithScopeId(org.GetPublicId())), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "GetAccount(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetAccount(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
func TestList(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, wrap)
}
o, _ := iam.TestScopes(t, conn)
ams := password.TestAuthMethods(t, conn, o.GetPublicId(), 3)
amNoAccounts, amSomeAccounts, amOtherAccounts := ams[0], ams[1], ams[2]
var wantSomeAccounts []*pb.Account
for _, aa := range password.TestAccounts(t, conn, amSomeAccounts.GetPublicId(), 3) {
wantSomeAccounts = append(wantSomeAccounts, &pb.Account{
Id: aa.GetPublicId(),
AuthMethodId: aa.GetAuthMethodId(),
CreatedTime: aa.GetCreateTime().GetTimestamp(),
UpdatedTime: aa.GetUpdateTime().GetTimestamp(),
Scope: &scopes.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()},
Type: "password",
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"username": structpb.NewStringValue(aa.GetUserName())}},
})
}
var wantOtherAccounts []*pb.Account
for _, aa := range password.TestAccounts(t, conn, amOtherAccounts.GetPublicId(), 3) {
wantOtherAccounts = append(wantOtherAccounts, &pb.Account{
Id: aa.GetPublicId(),
AuthMethodId: aa.GetAuthMethodId(),
CreatedTime: aa.GetCreateTime().GetTimestamp(),
UpdatedTime: aa.GetUpdateTime().GetTimestamp(),
Scope: &scopes.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()},
Type: "password",
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"username": structpb.NewStringValue(aa.GetUserName())}},
})
}
cases := []struct {
name string
authMethod string
res *pbs.ListAccountsResponse
errCode codes.Code
}{
{
name: "List Some Accounts",
authMethod: amSomeAccounts.GetPublicId(),
res: &pbs.ListAccountsResponse{Items: wantSomeAccounts},
errCode: codes.OK,
},
{
name: "List Other Accounts",
authMethod: amOtherAccounts.GetPublicId(),
res: &pbs.ListAccountsResponse{Items: wantOtherAccounts},
errCode: codes.OK,
},
{
name: "List No Accounts",
authMethod: amNoAccounts.GetPublicId(),
res: &pbs.ListAccountsResponse{},
errCode: codes.OK,
},
// TODO: When an auth method doesn't exist, we should return a 404 instead of an empty list.
{
name: "Unfound Auth Method",
authMethod: password.AuthMethodPrefix + "_DoesntExis",
res: &pbs.ListAccountsResponse{},
errCode: codes.OK,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
s, err := accounts.NewService(hclog.L(), repoFn)
require.NoError(t, err, "Couldn't create new user service.")
got, gErr := s.ListAccounts(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.ListAccountsRequest{AuthMethodId: tc.authMethod})
assert.Equal(t, tc.errCode, status.Code(gErr), "ListAccounts() with auth method %q got error %v, wanted %v", tc.authMethod, gErr, tc.errCode)
assert.Empty(t, cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "ListUsers() with scope %q got response %q, wanted %q", tc.authMethod, got, tc.res)
})
}
}
func TestDelete(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, wrap)
}
o, _ := iam.TestScopes(t, conn)
ams := password.TestAuthMethods(t, conn, o.GetPublicId(), 2)
am1, wrongAm := ams[0], ams[1]
ac := password.TestAccounts(t, conn, am1.GetPublicId(), 1)[0]
wrongAc := password.TestAccounts(t, conn, wrongAm.GetPublicId(), 1)[0]
s, err := accounts.NewService(hclog.L(), repoFn)
require.NoError(t, err, "Error when getting new user service.")
cases := []struct {
name string
scope string
req *pbs.DeleteAccountRequest
res *pbs.DeleteAccountResponse
errCode codes.Code
}{
{
name: "Delete an existing token",
req: &pbs.DeleteAccountRequest{
AuthMethodId: am1.GetPublicId(),
Id: ac.GetPublicId(),
},
res: &pbs.DeleteAccountResponse{
Existed: true,
},
errCode: codes.OK,
},
{
name: "Delete account from wrong auth method",
req: &pbs.DeleteAccountRequest{
AuthMethodId: am1.GetPublicId(),
Id: wrongAc.GetPublicId(),
},
// TODO(toddknight): This should return Existed:false. Figure out if this test is testing something valid
// and if so make it pass.
res: &pbs.DeleteAccountResponse{
Existed: true,
},
errCode: codes.OK,
},
{
name: "Delete bad account id",
req: &pbs.DeleteAccountRequest{
AuthMethodId: am1.GetPublicId(),
Id: password.AccountPrefix + "_doesntexis",
},
res: &pbs.DeleteAccountResponse{
Existed: false,
},
errCode: codes.OK,
},
{
name: "Bad account id formatting",
req: &pbs.DeleteAccountRequest{
AuthMethodId: am1.GetPublicId(),
Id: "bad_format",
},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.DeleteAccount(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "DeleteAccount(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.EqualValuesf(tc.res, got, "DeleteAccount(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
func TestDelete_twice(t *testing.T) {
assert := assert.New(t)
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, wrap)
}
o, _ := iam.TestScopes(t, conn)
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
ac := password.TestAccounts(t, conn, am.GetPublicId(), 1)[0]
s, err := accounts.NewService(hclog.L(), repoFn)
require.NoError(t, err, "Error when getting new user service")
req := &pbs.DeleteAccountRequest{
AuthMethodId: am.GetPublicId(),
Id: ac.GetPublicId(),
}
got, gErr := s.DeleteAccount(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), req)
assert.NoError(gErr, "First attempt")
assert.True(got.GetExisted(), "Expected existed to be true for the first delete.")
got, gErr = s.DeleteAccount(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), req)
assert.NoError(gErr, "Second attempt")
assert.False(got.GetExisted(), "Expected existed to be false for the second delete.")
}
func TestCreate(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrap := db.TestWrapper(t)
repoFn := func() (*password.Repository, error) {
return password.NewRepository(rw, rw, wrap)
}
s, err := accounts.NewService(hclog.L(), repoFn)
require.NoError(t, err, "Error when getting new account service.")
o, _ := iam.TestScopes(t, conn)
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
defaultAccount := password.TestAccounts(t, conn, am.GetPublicId(), 1)[0]
defaultCreated, err := ptypes.Timestamp(defaultAccount.GetCreateTime().GetTimestamp())
require.NoError(t, err, "Error converting proto to timestamp.")
defaultSt, err := handlers.ProtoToStruct(&pb.PasswordAccountAttributes{Username: "thetestusername"})
require.NoError(t, err, "Error converting proto to struct.")
cases := []struct {
name string
req *pbs.CreateAccountRequest
res *pbs.CreateAccountResponse
errCode codes.Code
}{
{
name: "Create a valid Account",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
Name: &wrapperspb.StringValue{Value: "name"},
Description: &wrapperspb.StringValue{Value: "desc"},
Type: "password",
Attributes: defaultSt,
},
},
res: &pbs.CreateAccountResponse{
Uri: fmt.Sprintf("scopes/%s/auth-methods/%s/accounts/%s_", o.GetPublicId(), defaultAccount.GetAuthMethodId(), password.AccountPrefix),
Item: &pb.Account{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Name: &wrapperspb.StringValue{Value: "name"},
Description: &wrapperspb.StringValue{Value: "desc"},
Scope: &scopes.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()},
Type: "password",
Attributes: defaultSt,
},
},
errCode: codes.OK,
},
{
name: "Can't specify Id",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
Id: password.AccountPrefix + "_notallowed",
Type: "password",
Attributes: defaultSt,
},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Can't specify AuthMethodId",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Type: "password",
Attributes: defaultSt,
},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Can't specify Created Time",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
CreatedTime: ptypes.TimestampNow(),
Type: "password",
Attributes: defaultSt,
},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Can't specify Update Time",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
UpdatedTime: ptypes.TimestampNow(),
Type: "password",
Attributes: defaultSt,
},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Must specify type",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
Attributes: defaultSt,
},
},
res: nil,
errCode: codes.InvalidArgument,
},
{
name: "Must specify username for password type",
req: &pbs.CreateAccountRequest{
AuthMethodId: defaultAccount.GetAuthMethodId(),
Item: &pb.Account{
Type: "password",
},
},
res: nil,
errCode: codes.InvalidArgument,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, gErr := s.CreateAccount(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateAccount(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
if got != nil {
assert.Contains(got.GetUri(), tc.res.Uri)
assert.True(strings.HasPrefix(got.GetItem().GetId(), password.AccountPrefix+"_"))
gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime())
require.NoError(err, "Error converting proto to timestamp.")
gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime())
require.NoError(err, "Error converting proto to timestamp.")
// Verify it is a user created after the test setup's default user
assert.True(gotCreateTime.After(defaultCreated), "New account should have been created after default user. Was created %v, which is after %v", gotCreateTime, defaultCreated)
assert.True(gotUpdateTime.After(defaultCreated), "New account should have been updated after default user. Was updated %v, which is after %v", gotUpdateTime, defaultCreated)
// Clear all values which are hard to compare against.
got.Uri, tc.res.Uri = "", ""
got.Item.Id, tc.res.Item.Id = "", ""
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
}
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateAccount(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -15,7 +15,6 @@ import (
"github.com/hashicorp/watchtower/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"github.com/stretchr/testify/assert"
@@ -82,8 +81,8 @@ func TestGet(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.GetAuthToken(auth.DisabledAuthTestContext(auth.WithScopeId(org.GetPublicId())), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "GetOrg(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "GetOrg(%q) got response %q, wanted %q", tc.req, got, tc.res)
assert.Equal(tc.errCode, status.Code(gErr), "GetAuthToken(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetAuthToken(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -168,8 +167,8 @@ func TestList(t *testing.T) {
require.NoError(t, err, "Couldn't create new user service.")
got, gErr := s.ListAuthTokens(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scope)), &pbs.ListAuthTokensRequest{})
assert.Equal(t, tc.errCode, status.Code(gErr), "ListUsers() with scope %q got error %v, wanted %v", tc.scope, gErr, tc.errCode)
assert.Empty(t, cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "ListUsers() with scope %q got response %q, wanted %q", tc.scope, got, tc.res)
assert.Equal(t, tc.errCode, status.Code(gErr), "ListAuthTokens() with scope %q got error %v, wanted %v", tc.scope, gErr, tc.errCode)
assert.Empty(t, cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "ListAuthTokens() with scope %q got response %q, wanted %q", tc.scope, got, tc.res)
})
}
}
@@ -246,8 +245,8 @@ func TestDelete(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.DeleteAuthToken(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scope)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "DeleteUser(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.EqualValuesf(tc.res, got, "DeleteUser(%q) got response %q, wanted %q", tc.req, got, tc.res)
assert.Equal(tc.errCode, status.Code(gErr), "DeleteAuthToken(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.EqualValuesf(tc.res, got, "DeleteAuthToken(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -270,7 +270,7 @@ func TestList(t *testing.T) {
got, gErr := s.ListGroups(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), &pbs.ListGroupsRequest{})
assert.Equal(tc.errCode, status.Code(gErr), "ListGroups(%q) got error %v, wanted %v", tc.scopeId, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "ListGroups(%q) got response %q, wanted %q", tc.scopeId, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListGroups(%q) got response %q, wanted %q", tc.scopeId, got, tc.res)
})
}
}
@@ -496,7 +496,7 @@ func TestCreate(t *testing.T) {
got, gErr := s.CreateGroup(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateGroup(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
if got != nil {
assert.True(strings.HasPrefix(got.GetUri(), tc.res.Uri), got.GetUri())
assert.Contains(got.GetUri(), tc.res.Uri)
assert.True(strings.HasPrefix(got.GetItem().GetId(), iam.GroupPrefix+"_"))
gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime())
require.NoError(err, "Error converting proto to timestamp.")
@@ -8,6 +8,7 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/wrappers"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/db"
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/hosts"
@@ -21,6 +22,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -107,7 +109,7 @@ func TestGet(t *testing.T) {
got, gErr := s.GetHostCatalog(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req)
assert.Equal(tc.errCode, status.Code(gErr), "GetHostCatalog(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "GetHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -296,7 +298,7 @@ func TestCreate(t *testing.T) {
got, gErr := s.CreateHostCatalog(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateHostCatalog(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
if got != nil {
assert.True(strings.HasPrefix(got.GetUri(), tc.res.GetUri()))
assert.Contains(got.GetUri(), tc.res.GetUri())
assert.True(strings.HasPrefix(got.GetItem().GetId(), static.HostCatalogPrefix))
gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime())
require.NoError(err, "Error converting proto to timestamp.")
@@ -311,7 +313,7 @@ func TestCreate(t *testing.T) {
got.Item.Id, tc.res.Item.Id = "", ""
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
}
assert.True(proto.Equal(got, tc.res), "CreateHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -604,7 +606,7 @@ func TestUpdate(t *testing.T) {
// Clear all values which are hard to compare against.
got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil
}
assert.True(proto.Equal(got, tc.res), "UpdateHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateHostCatalog(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -168,7 +168,7 @@ func TestGet(t *testing.T) {
got, gErr := s.GetRole(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), req)
assert.Equal(tc.errCode, status.Code(gErr), "GetRole(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "GetRole(%q) got response\n%q, wanted\n%q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetRole(%q) got response\n%q, wanted\n%q", req, got, tc.res)
})
}
}
@@ -249,7 +249,7 @@ func TestList(t *testing.T) {
got, gErr := s.ListRoles(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "ListRoles(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "ListRoles(%q) got response %q, wanted %q", tc.req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListRoles(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -472,7 +472,7 @@ func TestCreate(t *testing.T) {
got, gErr := s.CreateRole(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateRole(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
if got != nil {
assert.True(strings.HasPrefix(got.GetUri(), tc.res.Uri), "Expected %q to have the prefix %q", got.GetUri(), tc.res.GetUri())
assert.Contains(got.GetUri(), tc.res.Uri)
assert.True(strings.HasPrefix(got.GetItem().GetId(), iam.RolePrefix+"_"), "Expected %q to have the prefix %q", got.GetItem().GetId(), iam.RolePrefix+"_")
gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime())
require.NoError(err, "Error converting proto to timestamp.")
@@ -487,7 +487,7 @@ func TestCreate(t *testing.T) {
got.Item.Id, tc.res.Item.Id = "", ""
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
}
assert.True(proto.Equal(got, tc.res), "CreateRole(%q) got response\n%q, wanted\n%q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateRole(%q) got response\n%q, wanted\n%q", req, got, tc.res)
})
}
}
@@ -7,6 +7,7 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/wrappers"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/db"
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
@@ -18,6 +19,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
@@ -137,8 +139,8 @@ func TestGet(t *testing.T) {
require.NoError(err, "Couldn't create new project service.")
got, gErr := s.GetScope(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), req)
assert.Equal(tc.errCode, status.Code(gErr), "GetProject(%+v) got error\n%v, wanted\n%v", req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "GetProject(%q) got response\n%q, wanted\n%q", req, got, tc.res)
assert.Equal(tc.errCode, status.Code(gErr), "GetScope(%+v) got error\n%v, wanted\n%v", req, gErr, tc.errCode)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetScope(%q) got response\n%q, wanted\n%q", req, got, tc.res)
})
}
}
@@ -199,7 +201,7 @@ func TestList(t *testing.T) {
got, gErr := s.ListScopes(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "ListScopes(%+v) got error\n%v, wanted\n%v", tc.req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "ListScopes(%q) got response\n%q\nwanted\n%q", tc.req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListScopes(%q) got response\n%q\nwanted\n%q", tc.req, got, tc.res)
})
}
@@ -264,7 +266,7 @@ func TestList(t *testing.T) {
got, gErr := s.ListScopes(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "ListScopes(%+v) got error\n%v, wanted\n%v", tc.req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "ListScopes(%q) got response\n%q, wanted\n%q", tc.req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListScopes(%q) got response\n%q, wanted\n%q", tc.req, got, tc.res)
})
}
}
@@ -350,8 +352,8 @@ func TestDelete(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)
got, gErr := s.DeleteScope(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "DeleteProject(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.EqualValuesf(tc.res, got, "DeleteProject(%q) got response %q, wanted %q", tc.req, got, tc.res)
assert.Equal(tc.errCode, status.Code(gErr), "DeleteScope(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.EqualValuesf(tc.res, got, "DeleteScope(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -478,9 +480,9 @@ func TestCreate(t *testing.T) {
require.NoError(err, "Error when getting new project service.")
got, gErr := s.CreateScope(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateProject(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
assert.Equal(tc.errCode, status.Code(gErr), "CreateScope(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
if got != nil {
assert.True(strings.HasPrefix(got.GetUri(), tc.res.Uri))
assert.Contains(got.GetUri(), tc.res.Uri)
switch tc.scopeId {
case "global":
assert.True(strings.HasPrefix(got.GetItem().GetId(), "o_"))
@@ -500,7 +502,7 @@ func TestCreate(t *testing.T) {
got.Item.Id, tc.res.Item.Id = "", ""
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
}
assert.True(proto.Equal(got, tc.res), "CreateProject(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateScope(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -824,7 +826,7 @@ func TestUpdate(t *testing.T) {
// Clear all values which are hard to compare against.
got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil
}
assert.True(proto.Equal(got, tc.res), "UpdateScope(%q) got response\n%q, wanted\n%q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateScope(%q) got response\n%q, wanted\n%q", req, got, tc.res)
})
}
}
@@ -0,0 +1,30 @@
package handlers
import (
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
)
func StructToProto(fields *structpb.Struct, p proto.Message) error {
js, err := fields.MarshalJSON()
if err != nil {
return err
}
if err := protojson.Unmarshal(js, p); err != nil {
return err
}
return nil
}
func ProtoToStruct(p proto.Message) (*structpb.Struct, error) {
js, err := protojson.Marshal(p)
if err != nil {
return nil, err
}
st := &structpb.Struct{}
if err := protojson.Unmarshal(js, st); err != nil {
return nil, err
}
return st, nil
}
@@ -0,0 +1,49 @@
package handlers
import (
"testing"
structpb "github.com/golang/protobuf/ptypes/struct"
"github.com/google/go-cmp/cmp"
authpb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/auth"
hostpb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/hosts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/wrapperspb"
)
func TestStructToProtoToStruct(t *testing.T) {
testCases := []struct {
name string
pb proto.Message
wantJson string
}{
{
name: "password",
pb: &authpb.PasswordAccountAttributes{Username: "testun", Password: &wrapperspb.StringValue{Value: "testpw"}},
wantJson: `{"username": "testun", "password": "testpw"}`,
},
{
name: "ec2hostcatalog",
pb: &hostpb.AwsEc2HostCatalogDetails{Regions: []string{"r1", "r2"}, AccessKey: &wrapperspb.StringValue{Value: "test"}},
wantJson: `{"regions": ["r1", "r2"], "access_key": "test"}`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
st, err := ProtoToStruct(tc.pb)
require.NoError(t, err)
wantStruct := &structpb.Struct{}
require.NoError(t, protojson.Unmarshal([]byte(tc.wantJson), wantStruct))
assert.Empty(t, cmp.Diff(wantStruct, st, protocmp.Transform()))
newPwAttr := tc.pb.ProtoReflect().New().Interface()
StructToProto(st, newPwAttr)
assert.Equal(t, tc.pb, newPwAttr)
})
}
}
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/golang/protobuf/ptypes"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/watchtower/internal/auth"
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
@@ -19,6 +20,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
@@ -97,7 +99,7 @@ func TestGet(t *testing.T) {
got, gErr := s.GetUser(auth.DisabledAuthTestContext(auth.WithScopeId(u.GetScopeId())), req)
assert.Equal(tc.errCode, status.Code(gErr), "GetUser(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "GetUser(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetUser(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -159,7 +161,7 @@ func TestList(t *testing.T) {
got, gErr := s.ListUsers(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req)
assert.Equal(tc.errCode, status.Code(gErr), "ListUsers(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode)
assert.True(proto.Equal(got, tc.res), "ListUsers(%q) got response %q, wanted %q", tc.req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListUsers(%q) got response %q, wanted %q", tc.req, got, tc.res)
})
}
}
@@ -301,7 +303,7 @@ func TestCreate(t *testing.T) {
got, gErr := s.CreateUser(auth.DisabledAuthTestContext(auth.WithScopeId(defaultUser.GetScopeId())), req)
assert.Equal(tc.errCode, status.Code(gErr), "CreateUser(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
if got != nil {
assert.True(strings.HasPrefix(got.GetUri(), tc.res.Uri))
assert.Contains(got.GetUri(), tc.res.Uri)
assert.True(strings.HasPrefix(got.GetItem().GetId(), iam.UserPrefix+"_"))
gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime())
require.NoError(err, "Error converting proto to timestamp.")
@@ -316,7 +318,7 @@ func TestCreate(t *testing.T) {
got.Item.Id, tc.res.Item.Id = "", ""
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
}
assert.True(proto.Equal(got, tc.res), "CreateUser(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateUser(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}
@@ -564,7 +566,7 @@ func TestUpdate(t *testing.T) {
// Clear all values which are hard to compare against.
got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil
}
assert.True(proto.Equal(got, tc.res), "UpdateUser(%q) got response %q, wanted %q", req, got, tc.res)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateUser(%q) got response %q, wanted %q", req, got, tc.res)
})
}
}