Fix SSO support for anyconnect
This commit is contained in:
+53
-25
@@ -1620,35 +1620,46 @@ func openConnectEndpointStatusToProto(tag string, endpointStatus adapter.OpenCon
|
||||
Error: endpointStatus.Error,
|
||||
TunnelInfo: openConnectTunnelInfoToProto(endpointStatus.TunnelInfo),
|
||||
}
|
||||
if endpointStatus.AuthForm != nil {
|
||||
fields := common.Map(endpointStatus.AuthForm.Fields, func(field adapter.OpenConnectAuthFormField) *OpenConnectAuthFormField {
|
||||
return &OpenConnectAuthFormField{
|
||||
SubmissionKey: field.SubmissionKey,
|
||||
Name: field.Name,
|
||||
Label: field.Label,
|
||||
Kind: field.Kind,
|
||||
Value: field.Value,
|
||||
Options: common.Map(field.Options, func(option adapter.OpenConnectAuthFormChoice) *OpenConnectAuthFormChoice {
|
||||
return &OpenConnectAuthFormChoice{
|
||||
Value: option.Value,
|
||||
Label: option.Label,
|
||||
if endpointStatus.AuthChallenge != nil {
|
||||
challenge := &OpenConnectAuthChallenge{
|
||||
Id: endpointStatus.AuthChallenge.ID,
|
||||
Banner: endpointStatus.AuthChallenge.Banner,
|
||||
Message: endpointStatus.AuthChallenge.Message,
|
||||
Error: endpointStatus.AuthChallenge.Error,
|
||||
}
|
||||
if endpointStatus.AuthChallenge.Form != nil {
|
||||
challenge.Challenge = &OpenConnectAuthChallenge_Form{Form: &OpenConnectAuthForm{
|
||||
Fields: common.Map(endpointStatus.AuthChallenge.Form.Fields, func(field adapter.OpenConnectAuthFormField) *OpenConnectAuthFormField {
|
||||
return &OpenConnectAuthFormField{
|
||||
SubmissionKey: field.SubmissionKey,
|
||||
Name: field.Name,
|
||||
Label: field.Label,
|
||||
Kind: field.Kind,
|
||||
Value: field.Value,
|
||||
Options: common.Map(field.Options, func(option adapter.OpenConnectAuthFormChoice) *OpenConnectAuthFormChoice {
|
||||
return &OpenConnectAuthFormChoice{
|
||||
Value: option.Value,
|
||||
Label: option.Label,
|
||||
}
|
||||
}),
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
result.AuthForm = &OpenConnectAuthForm{
|
||||
Id: endpointStatus.AuthForm.ID,
|
||||
Banner: endpointStatus.AuthForm.Banner,
|
||||
Message: endpointStatus.AuthForm.Message,
|
||||
Error: endpointStatus.AuthForm.Error,
|
||||
Url: endpointStatus.AuthForm.URL,
|
||||
Fields: fields,
|
||||
}}
|
||||
}
|
||||
if endpointStatus.AuthChallenge.Browser != nil {
|
||||
challenge.Challenge = &OpenConnectAuthChallenge_Browser{Browser: &OpenConnectBrowserRequest{
|
||||
Url: endpointStatus.AuthChallenge.Browser.URL,
|
||||
FinalURL: endpointStatus.AuthChallenge.Browser.FinalURL,
|
||||
CookieNames: endpointStatus.AuthChallenge.Browser.CookieNames,
|
||||
HeaderNames: endpointStatus.AuthChallenge.Browser.HeaderNames,
|
||||
}}
|
||||
}
|
||||
result.AuthChallenge = challenge
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *StartedService) SubmitOpenConnectAuthForm(ctx context.Context, request *OpenConnectAuthFormSubmission) (*emptypb.Empty, error) {
|
||||
func (s *StartedService) SubmitOpenConnectAuthResponse(ctx context.Context, request *OpenConnectAuthResponseSubmission) (*emptypb.Empty, error) {
|
||||
err := s.waitForStarted(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1661,14 +1672,31 @@ func (s *StartedService) SubmitOpenConnectAuthForm(ctx context.Context, request
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = endpoint.CompleteAuthForm(request.FormID, request.Values)
|
||||
var authResponse adapter.OpenConnectAuthResponse
|
||||
form := request.GetForm()
|
||||
if form != nil {
|
||||
authResponse.Form = &adapter.OpenConnectAuthFormResponse{Values: form.Values}
|
||||
}
|
||||
browser := request.GetBrowser()
|
||||
if browser != nil {
|
||||
authResponse.Browser = &adapter.OpenConnectBrowserResult{
|
||||
FinalURL: browser.FinalURL,
|
||||
Cookies: common.Map(browser.Cookies, func(cookie *OpenConnectBrowserCookie) adapter.OpenConnectBrowserCookie {
|
||||
return adapter.OpenConnectBrowserCookie{Name: cookie.Name, Value: cookie.Value}
|
||||
}),
|
||||
Headers: common.Map(browser.Headers, func(header *OpenConnectBrowserHeader) adapter.OpenConnectBrowserHeader {
|
||||
return adapter.OpenConnectBrowserHeader{Name: header.Name, Values: header.Values}
|
||||
}),
|
||||
}
|
||||
}
|
||||
err = endpoint.CompleteAuthChallenge(request.ChallengeID, authResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *StartedService) CancelOpenConnectAuthForm(ctx context.Context, request *OpenConnectAuthFormCancel) (*emptypb.Empty, error) {
|
||||
func (s *StartedService) CancelOpenConnectAuthChallenge(ctx context.Context, request *OpenConnectAuthChallengeCancel) (*emptypb.Empty, error) {
|
||||
err := s.waitForStarted(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1681,7 +1709,7 @@ func (s *StartedService) CancelOpenConnectAuthForm(ctx context.Context, request
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = endpoint.CancelAuthForm(request.FormID)
|
||||
err = endpoint.CancelAuthChallenge(request.ChallengeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+733
-302
File diff suppressed because it is too large
Load Diff
@@ -39,8 +39,8 @@ service StartedService {
|
||||
rpc ProvideUSBDevices(stream USBProviderMessage) returns (stream USBServerMessage) {}
|
||||
rpc SubscribeUSBIPServerStatus(google.protobuf.Empty) returns (stream USBIPServerStatusUpdate) {}
|
||||
rpc SubscribeOpenConnectStatus(google.protobuf.Empty) returns (stream OpenConnectStatusUpdate) {}
|
||||
rpc SubmitOpenConnectAuthForm(OpenConnectAuthFormSubmission) returns (google.protobuf.Empty) {}
|
||||
rpc CancelOpenConnectAuthForm(OpenConnectAuthFormCancel) returns (google.protobuf.Empty) {}
|
||||
rpc SubmitOpenConnectAuthResponse(OpenConnectAuthResponseSubmission) returns (google.protobuf.Empty) {}
|
||||
rpc CancelOpenConnectAuthChallenge(OpenConnectAuthChallengeCancel) returns (google.protobuf.Empty) {}
|
||||
rpc SubscribeOpenVPNStatus(google.protobuf.Empty) returns (stream OpenVPNStatusUpdate) {}
|
||||
rpc SubmitOpenVPNChallengeResponse(OpenVPNChallengeSubmission) returns (google.protobuf.Empty) {}
|
||||
rpc CancelOpenVPNChallenge(OpenVPNChallengeCancel) returns (google.protobuf.Empty) {}
|
||||
@@ -532,7 +532,7 @@ message OpenConnectEndpointStatus {
|
||||
string endpointTag = 1;
|
||||
string state = 2;
|
||||
string stateText = 3;
|
||||
OpenConnectAuthForm authForm = 4;
|
||||
OpenConnectAuthChallenge authChallenge = 4;
|
||||
string error = 5;
|
||||
OpenConnectTunnelInfo tunnelInfo = 6;
|
||||
}
|
||||
@@ -548,13 +548,19 @@ message OpenConnectTunnelInfo {
|
||||
int64 connectedSince = 8;
|
||||
}
|
||||
|
||||
message OpenConnectAuthForm {
|
||||
message OpenConnectAuthChallenge {
|
||||
string id = 1;
|
||||
string banner = 2;
|
||||
string message = 3;
|
||||
string error = 4;
|
||||
string url = 5;
|
||||
repeated OpenConnectAuthFormField fields = 6;
|
||||
oneof challenge {
|
||||
OpenConnectAuthForm form = 5;
|
||||
OpenConnectBrowserRequest browser = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message OpenConnectAuthForm {
|
||||
repeated OpenConnectAuthFormField fields = 1;
|
||||
}
|
||||
|
||||
message OpenConnectAuthFormField {
|
||||
@@ -571,15 +577,45 @@ message OpenConnectAuthFormChoice {
|
||||
string label = 2;
|
||||
}
|
||||
|
||||
message OpenConnectAuthFormSubmission {
|
||||
string endpointTag = 1;
|
||||
string formID = 2;
|
||||
map<string, string> values = 3;
|
||||
message OpenConnectBrowserRequest {
|
||||
string url = 1;
|
||||
string finalURL = 2;
|
||||
repeated string cookieNames = 3;
|
||||
repeated string headerNames = 4;
|
||||
}
|
||||
|
||||
message OpenConnectAuthFormCancel {
|
||||
message OpenConnectBrowserCookie {
|
||||
string name = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message OpenConnectBrowserHeader {
|
||||
string name = 1;
|
||||
repeated string values = 2;
|
||||
}
|
||||
|
||||
message OpenConnectAuthFormResponse {
|
||||
map<string, string> values = 1;
|
||||
}
|
||||
|
||||
message OpenConnectBrowserResult {
|
||||
string finalURL = 1;
|
||||
repeated OpenConnectBrowserCookie cookies = 2;
|
||||
repeated OpenConnectBrowserHeader headers = 3;
|
||||
}
|
||||
|
||||
message OpenConnectAuthResponseSubmission {
|
||||
string endpointTag = 1;
|
||||
string formID = 2;
|
||||
string challengeID = 2;
|
||||
oneof response {
|
||||
OpenConnectAuthFormResponse form = 3;
|
||||
OpenConnectBrowserResult browser = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message OpenConnectAuthChallengeCancel {
|
||||
string endpointTag = 1;
|
||||
string challengeID = 2;
|
||||
}
|
||||
|
||||
message OpenVPNStatusUpdate {
|
||||
|
||||
@@ -44,8 +44,8 @@ const (
|
||||
StartedService_ProvideUSBDevices_FullMethodName = "/daemon.StartedService/ProvideUSBDevices"
|
||||
StartedService_SubscribeUSBIPServerStatus_FullMethodName = "/daemon.StartedService/SubscribeUSBIPServerStatus"
|
||||
StartedService_SubscribeOpenConnectStatus_FullMethodName = "/daemon.StartedService/SubscribeOpenConnectStatus"
|
||||
StartedService_SubmitOpenConnectAuthForm_FullMethodName = "/daemon.StartedService/SubmitOpenConnectAuthForm"
|
||||
StartedService_CancelOpenConnectAuthForm_FullMethodName = "/daemon.StartedService/CancelOpenConnectAuthForm"
|
||||
StartedService_SubmitOpenConnectAuthResponse_FullMethodName = "/daemon.StartedService/SubmitOpenConnectAuthResponse"
|
||||
StartedService_CancelOpenConnectAuthChallenge_FullMethodName = "/daemon.StartedService/CancelOpenConnectAuthChallenge"
|
||||
StartedService_SubscribeOpenVPNStatus_FullMethodName = "/daemon.StartedService/SubscribeOpenVPNStatus"
|
||||
StartedService_SubmitOpenVPNChallengeResponse_FullMethodName = "/daemon.StartedService/SubmitOpenVPNChallengeResponse"
|
||||
StartedService_CancelOpenVPNChallenge_FullMethodName = "/daemon.StartedService/CancelOpenVPNChallenge"
|
||||
@@ -84,8 +84,8 @@ type StartedServiceClient interface {
|
||||
ProvideUSBDevices(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[USBProviderMessage, USBServerMessage], error)
|
||||
SubscribeUSBIPServerStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[USBIPServerStatusUpdate], error)
|
||||
SubscribeOpenConnectStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OpenConnectStatusUpdate], error)
|
||||
SubmitOpenConnectAuthForm(ctx context.Context, in *OpenConnectAuthFormSubmission, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
CancelOpenConnectAuthForm(ctx context.Context, in *OpenConnectAuthFormCancel, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
SubmitOpenConnectAuthResponse(ctx context.Context, in *OpenConnectAuthResponseSubmission, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
CancelOpenConnectAuthChallenge(ctx context.Context, in *OpenConnectAuthChallengeCancel, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
SubscribeOpenVPNStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OpenVPNStatusUpdate], error)
|
||||
SubmitOpenVPNChallengeResponse(ctx context.Context, in *OpenVPNChallengeSubmission, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
CancelOpenVPNChallenge(ctx context.Context, in *OpenVPNChallengeCancel, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
@@ -512,20 +512,20 @@ func (c *startedServiceClient) SubscribeOpenConnectStatus(ctx context.Context, i
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_SubscribeOpenConnectStatusClient = grpc.ServerStreamingClient[OpenConnectStatusUpdate]
|
||||
|
||||
func (c *startedServiceClient) SubmitOpenConnectAuthForm(ctx context.Context, in *OpenConnectAuthFormSubmission, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
func (c *startedServiceClient) SubmitOpenConnectAuthResponse(ctx context.Context, in *OpenConnectAuthResponseSubmission, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, StartedService_SubmitOpenConnectAuthForm_FullMethodName, in, out, cOpts...)
|
||||
err := c.cc.Invoke(ctx, StartedService_SubmitOpenConnectAuthResponse_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *startedServiceClient) CancelOpenConnectAuthForm(ctx context.Context, in *OpenConnectAuthFormCancel, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
func (c *startedServiceClient) CancelOpenConnectAuthChallenge(ctx context.Context, in *OpenConnectAuthChallengeCancel, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, StartedService_CancelOpenConnectAuthForm_FullMethodName, in, out, cOpts...)
|
||||
err := c.cc.Invoke(ctx, StartedService_CancelOpenConnectAuthChallenge_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -604,8 +604,8 @@ type StartedServiceServer interface {
|
||||
ProvideUSBDevices(grpc.BidiStreamingServer[USBProviderMessage, USBServerMessage]) error
|
||||
SubscribeUSBIPServerStatus(*emptypb.Empty, grpc.ServerStreamingServer[USBIPServerStatusUpdate]) error
|
||||
SubscribeOpenConnectStatus(*emptypb.Empty, grpc.ServerStreamingServer[OpenConnectStatusUpdate]) error
|
||||
SubmitOpenConnectAuthForm(context.Context, *OpenConnectAuthFormSubmission) (*emptypb.Empty, error)
|
||||
CancelOpenConnectAuthForm(context.Context, *OpenConnectAuthFormCancel) (*emptypb.Empty, error)
|
||||
SubmitOpenConnectAuthResponse(context.Context, *OpenConnectAuthResponseSubmission) (*emptypb.Empty, error)
|
||||
CancelOpenConnectAuthChallenge(context.Context, *OpenConnectAuthChallengeCancel) (*emptypb.Empty, error)
|
||||
SubscribeOpenVPNStatus(*emptypb.Empty, grpc.ServerStreamingServer[OpenVPNStatusUpdate]) error
|
||||
SubmitOpenVPNChallengeResponse(context.Context, *OpenVPNChallengeSubmission) (*emptypb.Empty, error)
|
||||
CancelOpenVPNChallenge(context.Context, *OpenVPNChallengeCancel) (*emptypb.Empty, error)
|
||||
@@ -735,12 +735,12 @@ func (UnimplementedStartedServiceServer) SubscribeOpenConnectStatus(*emptypb.Emp
|
||||
return status.Error(codes.Unimplemented, "method SubscribeOpenConnectStatus not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) SubmitOpenConnectAuthForm(context.Context, *OpenConnectAuthFormSubmission) (*emptypb.Empty, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SubmitOpenConnectAuthForm not implemented")
|
||||
func (UnimplementedStartedServiceServer) SubmitOpenConnectAuthResponse(context.Context, *OpenConnectAuthResponseSubmission) (*emptypb.Empty, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SubmitOpenConnectAuthResponse not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) CancelOpenConnectAuthForm(context.Context, *OpenConnectAuthFormCancel) (*emptypb.Empty, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CancelOpenConnectAuthForm not implemented")
|
||||
func (UnimplementedStartedServiceServer) CancelOpenConnectAuthChallenge(context.Context, *OpenConnectAuthChallengeCancel) (*emptypb.Empty, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CancelOpenConnectAuthChallenge not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) SubscribeOpenVPNStatus(*emptypb.Empty, grpc.ServerStreamingServer[OpenVPNStatusUpdate]) error {
|
||||
@@ -1184,38 +1184,38 @@ func _StartedService_SubscribeOpenConnectStatus_Handler(srv interface{}, stream
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_SubscribeOpenConnectStatusServer = grpc.ServerStreamingServer[OpenConnectStatusUpdate]
|
||||
|
||||
func _StartedService_SubmitOpenConnectAuthForm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenConnectAuthFormSubmission)
|
||||
func _StartedService_SubmitOpenConnectAuthResponse_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenConnectAuthResponseSubmission)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(StartedServiceServer).SubmitOpenConnectAuthForm(ctx, in)
|
||||
return srv.(StartedServiceServer).SubmitOpenConnectAuthResponse(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: StartedService_SubmitOpenConnectAuthForm_FullMethodName,
|
||||
FullMethod: StartedService_SubmitOpenConnectAuthResponse_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(StartedServiceServer).SubmitOpenConnectAuthForm(ctx, req.(*OpenConnectAuthFormSubmission))
|
||||
return srv.(StartedServiceServer).SubmitOpenConnectAuthResponse(ctx, req.(*OpenConnectAuthResponseSubmission))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _StartedService_CancelOpenConnectAuthForm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenConnectAuthFormCancel)
|
||||
func _StartedService_CancelOpenConnectAuthChallenge_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenConnectAuthChallengeCancel)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(StartedServiceServer).CancelOpenConnectAuthForm(ctx, in)
|
||||
return srv.(StartedServiceServer).CancelOpenConnectAuthChallenge(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: StartedService_CancelOpenConnectAuthForm_FullMethodName,
|
||||
FullMethod: StartedService_CancelOpenConnectAuthChallenge_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(StartedServiceServer).CancelOpenConnectAuthForm(ctx, req.(*OpenConnectAuthFormCancel))
|
||||
return srv.(StartedServiceServer).CancelOpenConnectAuthChallenge(ctx, req.(*OpenConnectAuthChallengeCancel))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
@@ -1331,12 +1331,12 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _StartedService_TailscaleLogout_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SubmitOpenConnectAuthForm",
|
||||
Handler: _StartedService_SubmitOpenConnectAuthForm_Handler,
|
||||
MethodName: "SubmitOpenConnectAuthResponse",
|
||||
Handler: _StartedService_SubmitOpenConnectAuthResponse_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CancelOpenConnectAuthForm",
|
||||
Handler: _StartedService_CancelOpenConnectAuthForm_Handler,
|
||||
MethodName: "CancelOpenConnectAuthChallenge",
|
||||
Handler: _StartedService_CancelOpenConnectAuthChallenge_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SubmitOpenVPNChallengeResponse",
|
||||
|
||||
Reference in New Issue
Block a user