From 3883a1d270eddaa62a67617a22b18bd56b88d50d Mon Sep 17 00:00:00 2001 From: Michael Myers Date: Wed, 4 Dec 2024 13:45:42 -0600 Subject: [PATCH] Hide review box if user cannot review access requests oss counterpart for https://github.com/gravitational/teleport.e/pull/5628 This adds some testing to the view as well as the equivalent to the web solution for Connect. Connect was missing the [recently added](https://github.com/gravitational/teleport/pull/48536) `ReviewRequests` field in the user ACL, so I added it here. Because this is handled in the tsh code, we don't have to worry about backward compatibility here for Connect right? --- .../go/teleport/lib/teleterm/v1/cluster.pb.go | 80 +++++++++++-------- .../ts/teleport/lib/teleterm/v1/cluster_pb.ts | 15 +++- lib/teleterm/clusters/cluster.go | 1 + proto/teleport/lib/teleterm/v1/cluster.proto | 2 + .../RequestReview/RequestReview.tsx | 1 + .../RequestView/RequestView.test.tsx | 70 ++++++++++++++++ .../teleterm/src/services/tshd/testHelpers.ts | 1 + .../useReviewAccessRequest.ts | 4 +- 8 files changed, 139 insertions(+), 35 deletions(-) create mode 100644 web/packages/shared/components/AccessRequests/ReviewRequests/RequestView/RequestView.test.tsx diff --git a/gen/proto/go/teleport/lib/teleterm/v1/cluster.pb.go b/gen/proto/go/teleport/lib/teleterm/v1/cluster.pb.go index e27db690a6087..52f0c5e6eaa10 100644 --- a/gen/proto/go/teleport/lib/teleterm/v1/cluster.pb.go +++ b/gen/proto/go/teleport/lib/teleterm/v1/cluster.pb.go @@ -465,6 +465,8 @@ type ACL struct { RecordedSessions *ResourceAccess `protobuf:"bytes,13,opt,name=recorded_sessions,json=recordedSessions,proto3" json:"recorded_sessions,omitempty"` // active_sessions defines access to active sessions. ActiveSessions *ResourceAccess `protobuf:"bytes,14,opt,name=active_sessions,json=activeSessions,proto3" json:"active_sessions,omitempty"` + // review_requests defines the ability to review requests + ReviewRequests *bool `protobuf:"varint,15,opt,name=review_requests,json=reviewRequests,proto3,oneof" json:"review_requests,omitempty"` } func (x *ACL) Reset() { @@ -588,6 +590,13 @@ func (x *ACL) GetActiveSessions() *ResourceAccess { return nil } +func (x *ACL) GetReviewRequests() bool { + if x != nil && x.ReviewRequests != nil { + return *x.ReviewRequests + } + return false +} + // ResourceAccess describes access verbs type ResourceAccess struct { state protoimpl.MessageState @@ -814,7 +823,7 @@ var file_teleport_lib_teleterm_v1_cluster_proto_rawDesc = []byte{ 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x53, 0x4f, 0x10, 0x02, 0x22, - 0xc8, 0x07, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x51, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x5f, + 0x8a, 0x08, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x51, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, @@ -873,38 +882,42 @@ var file_teleport_lib_teleterm_v1_cluster_proto_rawDesc = []byte{ 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x0e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, - 0x52, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x0e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, 0x69, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x04, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x64, 0x69, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x04, 0x65, 0x64, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x73, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x75, 0x73, 0x65, 0x22, 0x7b, 0x0a, 0x08, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x61, 0x64, 0x76, 0x61, 0x6e, - 0x63, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x64, 0x76, 0x61, - 0x6e, 0x63, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x69, 0x73, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, - 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, - 0x64, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2a, 0x73, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x48, 0x4f, - 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x48, 0x4f, - 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x55, - 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x48, 0x4f, - 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, - 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x42, 0x54, 0x5a, - 0x52, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x0f, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4a, 0x04, 0x08, 0x01, + 0x10, 0x02, 0x52, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, 0x0a, + 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, + 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x04, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x64, 0x69, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x65, 0x64, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x75, 0x73, 0x65, 0x22, 0x7b, 0x0a, + 0x08, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x61, 0x64, 0x76, + 0x61, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x64, + 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x69, 0x73, 0x5f, 0x75, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x61, + 0x73, 0x65, 0x64, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2a, 0x73, 0x0a, 0x0d, 0x53, 0x68, + 0x6f, 0x77, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x1a, 0x53, + 0x48, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x53, + 0x48, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x52, 0x45, + 0x51, 0x55, 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x53, + 0x48, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x5f, 0x41, 0x43, + 0x43, 0x45, 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x42, + 0x54, 0x5a, 0x52, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x72, 0x6d, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -963,6 +976,7 @@ func file_teleport_lib_teleterm_v1_cluster_proto_init() { if File_teleport_lib_teleterm_v1_cluster_proto != nil { return } + file_teleport_lib_teleterm_v1_cluster_proto_msgTypes[2].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/gen/proto/ts/teleport/lib/teleterm/v1/cluster_pb.ts b/gen/proto/ts/teleport/lib/teleterm/v1/cluster_pb.ts index 297e11f43715d..e7d1d3bfed4cf 100644 --- a/gen/proto/ts/teleport/lib/teleterm/v1/cluster_pb.ts +++ b/gen/proto/ts/teleport/lib/teleterm/v1/cluster_pb.ts @@ -300,6 +300,12 @@ export interface ACL { * @generated from protobuf field: teleport.lib.teleterm.v1.ResourceAccess active_sessions = 14; */ activeSessions?: ResourceAccess; + /** + * review_requests defines the ability to review requests + * + * @generated from protobuf field: optional bool review_requests = 15; + */ + reviewRequests?: boolean; } /** * ResourceAccess describes access verbs @@ -649,7 +655,8 @@ class ACL$Type extends MessageType { { no: 11, name: "kubeservers", kind: "message", T: () => ResourceAccess }, { no: 12, name: "access_requests", kind: "message", T: () => ResourceAccess }, { no: 13, name: "recorded_sessions", kind: "message", T: () => ResourceAccess }, - { no: 14, name: "active_sessions", kind: "message", T: () => ResourceAccess } + { no: 14, name: "active_sessions", kind: "message", T: () => ResourceAccess }, + { no: 15, name: "review_requests", kind: "scalar", opt: true, T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): ACL { @@ -702,6 +709,9 @@ class ACL$Type extends MessageType { case /* teleport.lib.teleterm.v1.ResourceAccess active_sessions */ 14: message.activeSessions = ResourceAccess.internalBinaryRead(reader, reader.uint32(), options, message.activeSessions); break; + case /* optional bool review_requests */ 15: + message.reviewRequests = reader.bool(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -753,6 +763,9 @@ class ACL$Type extends MessageType { /* teleport.lib.teleterm.v1.ResourceAccess active_sessions = 14; */ if (message.activeSessions) ResourceAccess.internalBinaryWrite(message.activeSessions, writer.tag(14, WireType.LengthDelimited).fork(), options).join(); + /* optional bool review_requests = 15; */ + if (message.reviewRequests !== undefined) + writer.tag(15, WireType.Varint).bool(message.reviewRequests); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); diff --git a/lib/teleterm/clusters/cluster.go b/lib/teleterm/clusters/cluster.go index 3924941cdac9a..a6ee094266011 100644 --- a/lib/teleterm/clusters/cluster.go +++ b/lib/teleterm/clusters/cluster.go @@ -213,6 +213,7 @@ func (c *Cluster) GetWithDetails(ctx context.Context, authClient authclient.Clie Dbs: convertToAPIResourceAccess(userACL.DBServers), Kubeservers: convertToAPIResourceAccess(userACL.KubeServers), AccessRequests: convertToAPIResourceAccess(userACL.AccessRequests), + ReviewRequests: &userACL.ReviewRequests, } withDetails := &ClusterWithDetails{ diff --git a/proto/teleport/lib/teleterm/v1/cluster.proto b/proto/teleport/lib/teleterm/v1/cluster.proto index f0bafaf348419..a6aaaaf92c8ed 100644 --- a/proto/teleport/lib/teleterm/v1/cluster.proto +++ b/proto/teleport/lib/teleterm/v1/cluster.proto @@ -141,6 +141,8 @@ message ACL { ResourceAccess recorded_sessions = 13; // active_sessions defines access to active sessions. ResourceAccess active_sessions = 14; + // review_requests defines the ability to review requests + optional bool review_requests = 15; } // ResourceAccess describes access verbs diff --git a/web/packages/shared/components/AccessRequests/ReviewRequests/RequestView/RequestReview/RequestReview.tsx b/web/packages/shared/components/AccessRequests/ReviewRequests/RequestView/RequestReview/RequestReview.tsx index c21e4295c3afc..1c676229d0a78 100644 --- a/web/packages/shared/components/AccessRequests/ReviewRequests/RequestView/RequestReview/RequestReview.tsx +++ b/web/packages/shared/components/AccessRequests/ReviewRequests/RequestView/RequestReview/RequestReview.tsx @@ -114,6 +114,7 @@ export default function RequestReview({ {({ validator }) => ( . + */ + +import { render, screen } from 'design/utils/testing'; + +import { makeEmptyAttempt, makeSuccessAttempt } from 'shared/hooks/useAsync'; + +import { requestRolePending } from '../../fixtures'; + +import { RequestView, RequestViewProps } from './RequestView'; +import { RequestFlags } from './types'; + +const reviewBoxId = 'review_box'; + +const sampleFlags: RequestFlags = { + canAssume: false, + isAssumed: false, + canDelete: false, + canReview: true, + ownRequest: false, + isPromoted: false, +}; + +const sample: RequestViewProps = { + user: 'loggedInUsername', + fetchRequestAttempt: makeSuccessAttempt(requestRolePending), + submitReviewAttempt: makeEmptyAttempt(), + getFlags: () => sampleFlags, + confirmDelete: false, + toggleConfirmDelete: () => null, + submitReview: () => null, + assumeRole: () => null, + fetchSuggestedAccessListsAttempt: makeSuccessAttempt([]), + assumeRoleAttempt: makeEmptyAttempt(), + assumeAccessList: () => null, + deleteRequestAttempt: makeEmptyAttempt(), + deleteRequest: () => null, +}; + +describe('Request View', () => { + test('renders review box if user can review', async () => { + render(); + expect(screen.getByTestId(reviewBoxId)).toBeInTheDocument(); + }); + + test('does not render review box is user cannot review', async () => { + const testState = { + ...sample, + getFlags: () => ({ ...sampleFlags, canReview: false }), + }; + + render(); + expect(screen.queryByTestId(reviewBoxId)).not.toBeInTheDocument(); + }); +}); diff --git a/web/packages/teleterm/src/services/tshd/testHelpers.ts b/web/packages/teleterm/src/services/tshd/testHelpers.ts index f05ad0c234094..3c1daab9c4f65 100644 --- a/web/packages/teleterm/src/services/tshd/testHelpers.ts +++ b/web/packages/teleterm/src/services/tshd/testHelpers.ts @@ -225,6 +225,7 @@ export const makeLoggedInUser = ( delete: true, use: true, }, + reviewRequests: true, }, sshLogins: [], roles: [], diff --git a/web/packages/teleterm/src/ui/DocumentAccessRequests/ReviewAccessRequest/useReviewAccessRequest.ts b/web/packages/teleterm/src/ui/DocumentAccessRequests/ReviewAccessRequest/useReviewAccessRequest.ts index e85b0b278789a..ed0f182ca9c33 100644 --- a/web/packages/teleterm/src/ui/DocumentAccessRequests/ReviewAccessRequest/useReviewAccessRequest.ts +++ b/web/packages/teleterm/src/ui/DocumentAccessRequests/ReviewAccessRequest/useReviewAccessRequest.ts @@ -181,11 +181,13 @@ function getRequestFlags( ? reviewed.state === 'PENDING' : request.state === 'PENDING'; + const canReview = !ownRequest && isPendingState && user.acl.reviewRequests; + return { canAssume, isAssumed, canDelete, - canReview: !ownRequest && isPendingState, + canReview, isPromoted, ownRequest, };