googleads / google-ads-dotnet

This project hosts the .NET client library for the Google Ads API.

Home Page:https://developers.google.com/google-ads/api

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error_PermissionDenied in MutateCustomerUserAccessInvitation

Savvelev opened this issue · comments

Describe the bug:
Faced the problem of canceling invitations to the manager account.
The invitation uses the CustomerClientLinkService.MutateCustomerClientLink service.
Using CustomerClientLinkOperation with ClientCustomer and its identifier and Status ManagerLinkStatusEnum.Types.ManagerLinkStatus.Pending requests go, clients receive letters and become in the manager account hierarchy. All functionality works. LoginCustomerId = CustomerId of the manager. Everything is as described in the documentation.
The problem appeared when I ran into a limit on 20 Pending
requests and you need to withdraw irrelevant ones.
CustomerClientLinkOperation doesn't make it possible to do this, as I understand it.
In the documentation, I found CustomerUserAccessInvitationOperation and the remove operation.
Faced the problem described in the title : USER_PERMISSION_DENIED
The request contains LoginCustomerId = CustomerId of the manager. The previous logic only confirms that everything should work, like other methods that, after gaining access, interact with subordinate accounts - change, update. And such requests should have LoginCustomerId. Through the web interface, the recall of the invite works.
What to do in such a situation?
Steps to Reproduce:

Here is my client for which I am creating a Google.Ads.GoogleAds.Services.V12.CustomerUserAccessInvitationService service. (Version 13 gives the same error)

_client = new GoogleAdsClient(new GoogleAdsConfig
{
    OAuth2Mode = Google.Ads.Gax.Config.OAuth2Flow.APPLICATION,
    DeveloperToken = "***",
    OAuth2ClientId = "***.apps.googleusercontent.com",
    OAuth2ClientSecret = "***",
    OAuth2RefreshToken = "***",
    LoginCustomerId = "###" // manager account id
});
_service = _client.GetService(Google.Ads.GoogleAds.Services.V12.GoogleAdsService);

A small piece of code that calls a function

var customerClientLinkService =
                _user.GetService(Google.Ads.GoogleAds.Services.V12.CustomerUserAccessInvitationService);
            
            var customerId = #########;;
            var invitationId = #########;
            var request = new MutateCustomerUserAccessInvitationRequest
            {
                CustomerId = customerId,
                Operation = new CustomerUserAccessInvitationOperation
                {
                    Remove = $"customers/{customerId}/customerUserAccessInvitations/{invitationId}" 
                }
            };

            try
            {

                var response =
                    customerClientLinkService.MutateCustomerUserAccessInvitation(request);

                var customerClientLinkResourceName = response.Result.ResourceName;
            }
            catch (GoogleAdsException ex)
            { 
                if (ex.Failure.Errors.Count > 0)
                    throw new Exception(string.Join("; ", ex.Failure.Errors.Select(er => er.Message)), ex);

                throw new Exception($"ex.Message: {ex.Message}", ex);
            }

customerId = #########;;
invitationId = #########;
I'm getting from another service which returns all links to me.

const string defaultCustomerClientLinkQuery = @"
                SELECT 
                    customer_client_link.client_customer,
                    customer_client_link.hidden,
                    customer_client_link.manager_link_id,
                    customer_client_link.resource_name,
                    customer_client_link.status,
                    customer.id
                FROM customer_client_link";

            var googleAdsService = _user.GetService(Google.Ads.GoogleAds.Services.V12.GoogleAdsService);

            try
            {
                googleAdsService.SearchStream(WithoutHyphens(managerCustomerId), defaultCustomerClientLinkQuery,
                    delegate(SearchGoogleAdsStreamResponse response)
                    {
                        result = (from row in response.Results
                            group row.CustomerClientLink by IdToLong(
                                row.CustomerClientLink.ClientCustomer.Split('/')[1]))
                            .ToDictionary(x => x.Key, 
                                x => 
                                    x.FirstOrDefault(y => 
                                        y.Status == ManagerLinkStatusEnum.Types.ManagerLinkStatus.Active)?.Status 
                                    ?? x.Last().Status);
                    });
            }

As a result, the following error:

Google.Ads.GoogleAds.V12.Errors.GoogleAdsException
  HResult=0x80131500
  Message=Status(StatusCode="PermissionDenied", Detail="The caller does not have permission", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1680774582.737000000","description":"Error received from peer ipv4:173.194.222.95:443","file":"..\..\..\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"The caller does not have permission","grpc_status":7}")
  Source=Google.Ads.Gax
  StackTrace:
   at Google.Ads.Gax.Interceptors.UnaryRpcInterceptor.<Intercept>d__1`2.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Api.Gax.Grpc.ApiCall.GrpcCallAdapter`2.<>c__DisplayClass4_0.<<CallAsync>g__WaitAndCallHandlers|0>d.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Google.Api.Gax.TaskExtensions.WaitWithUnwrappedExceptions(Task task)
   at Google.Api.Gax.Grpc.ApiCall.GrpcCallAdapter`2.CallSync(TRequest request, CallSettings callSettings)
   at Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass1_0`2.<WithRetry>b__0(TRequest request, CallSettings callSettings)
   at Google.Api.Gax.Grpc.ApiCall`2.<>c__DisplayClass12_0.<WithCallSettingsOverlay>b__1(TRequest req, CallSettings cs)
   at Google.Api.Gax.Grpc.ApiCall`2.Sync(TRequest request, CallSettings perCallCallSettings)
   at Google.Ads.GoogleAds.V12.Services.CustomerUserAccessInvitationServiceClientImpl.MutateCustomerUserAccessInvitation(MutateCustomerUserAccessInvitationRequest request, CallSettings callSettings)
   at ****.DAL.ExternalServices.GoogleAds.Services.GoogleAdsApiService.CancelInvitation(Int64 clientId) in C:\Repos\****\****\****.DAL\ExternalServices\GoogleAds\Services\GoogleAdsManagerAccountApiService.cs:line 130

  This exception was originally thrown at this call stack:
    [External Code]
    ****.DAL.ExternalServices.GoogleAds.Services.GoogleAdsApiService.CancelInvitation(long) in GoogleAdsManagerAccountApiService.cs

Client library version and API version:
Google.Ads.GoogleAds.Core version: 2.1/0
Google.Ads.GoogleAds version: 14.2.0
Google.Ads.Gax 4.0.0
.NET version: Framework 4.8
Operating system ( Windows10)

Request/Response Logs:

Anything else we should know about your project / environment

Sorry for this answer, I just now noticed that the replay is like this. Already deleted. Github does not show me the email address where you should write, replacing everything with a template with *. The mail agent showed me your name for a reply. I answered there.

Github doesn't show me the email address to write to, replacing everything with a wildcard with *. What is your email address to resolve the issue? I need your help. My problem is still not resolved.
Regards, Mikhail

Hi, This issue is specific to Google Ads API, so could you share this exact information with @.*** and add a note that this was redirected from this issue tracker?

On Thu, Apr 6, 2023, 8:13 AM Mikhail @.> wrote: Describe the bug: Faced the problem of canceling invitations to the manager account. The invitation uses the CustomerClientLinkService.MutateCustomerClientLink service. Using CustomerClientLinkOperation with ClientCustomer and its identifier and Status ManagerLinkStatusEnum.Types.ManagerLinkStatus.Pending requests go, clients receive letters and become in the manager account hierarchy. All functionality works. LoginCustomerId = CustomerId of the manager. Everything is as described in the documentation. The problem appeared when I ran into a limit on 20 Pending requests and you need to withdraw irrelevant ones. CustomerClientLinkOperation doesn't make it possible to do this, as I understand it. In the documentation, I found CustomerUserAccessInvitationOperation and the remove operation. Faced the problem described in the title : USER_PERMISSION_DENIED The request contains LoginCustomerId = CustomerId of the manager. The previous logic only confirms that everything should work, like other methods that, after gaining access, interact with subordinate accounts - change, update. And such requests should have LoginCustomerId. Through the web interface, the recall of the invite works. What to do in such a situation? Steps to Reproduce: Here is my client for which I am creating a Google.Ads.GoogleAds.Services.V12.CustomerUserAccessInvitationService service. (Version 13 gives the same error) _client = new GoogleAdsClient(new GoogleAdsConfig { OAuth2Mode = Google.Ads.Gax.Config.OAuth2Flow.APPLICATION, DeveloperToken = "", OAuth2ClientId = ".apps.googleusercontent.com", OAuth2ClientSecret = "", OAuth2RefreshToken = "", LoginCustomerId = "###" // manager account id }); _service = _client.GetService(Google.Ads.GoogleAds.Services.V12.GoogleAdsService); A small piece of code that calls a function var customerClientLinkService = _user.GetService(Google.Ads.GoogleAds.Services.V12.CustomerUserAccessInvitationService); var customerId = #########;; var invitationId = #########; var request = new MutateCustomerUserAccessInvitationRequest { CustomerId = customerId, Operation = new CustomerUserAccessInvitationOperation { Remove = $"customers/{customerId}/customerUserAccessInvitations/{invitationId}" } }; try { var response = customerClientLinkService.MutateCustomerUserAccessInvitation(request); var customerClientLinkResourceName = response.Result.ResourceName; } catch (GoogleAdsException ex) { if (ex.Failure.Errors.Count > 0) throw new Exception(string.Join("; ", ex.Failure.Errors.Select(er => er.Message)), ex); throw new Exception($"ex.Message: {ex.Message}", ex); } customerId = #########;; invitationId = #########; I'm getting from another service which returns all links to me. const string defaultCustomerClientLinkQuery = @" SELECT customer_client_link.client_customer, customer_client_link.hidden, customer_client_link.manager_link_id, customer_client_link.resource_name, customer_client_link.status, customer.id FROM customer_client_link"; var googleAdsService = _user.GetService(Google.Ads.GoogleAds.Services.V12.GoogleAdsService); try { googleAdsService.SearchStream(WithoutHyphens(managerCustomerId), defaultCustomerClientLinkQuery, delegate(SearchGoogleAdsStreamResponse response) { result = (from row in response.Results group row.CustomerClientLink by IdToLong( row.CustomerClientLink.ClientCustomer.Split('/')[1])) .ToDictionary(x => x.Key, x => x.FirstOrDefault(y => y.Status == ManagerLinkStatusEnum.Types.ManagerLinkStatus.Active)?.Status ?? x.Last().Status); }); } As a result, the following error: Google.Ads.GoogleAds.V12.Errors.GoogleAdsException HResult=0x80131500 Message=Status(StatusCode="PermissionDenied", Detail="The caller does not have permission", DebugException="Grpc.Core.Internal.CoreErrorDetailException: @.","description":"Error received from peer ipv4:173.194.222.95:443","file":"......\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"The caller does not have permission","grpc_status":7}") Source=Google.Ads.Gax StackTrace: at Google.Ads.Gax.Interceptors.UnaryRpcInterceptor.d__12.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Api.Gax.Grpc.ApiCall.GrpcCallAdapter2.<>c__DisplayClass4_0.<g__WaitAndCallHandlers|0>d.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Google.Api.Gax.TaskExtensions.WaitWithUnwrappedExceptions(Task task) at Google.Api.Gax.Grpc.ApiCall.GrpcCallAdapter2.CallSync(TRequest request, CallSettings callSettings) at Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass1_02.b__0(TRequest request, CallSettings callSettings) at Google.Api.Gax.Grpc.ApiCall2.<>c__DisplayClass12_0.<WithCallSettingsOverlay>b__1(TRequest req, CallSettings cs) at Google.Api.Gax.Grpc.ApiCall2.Sync(TRequest request, CallSettings perCallCallSettings) at Google.Ads.GoogleAds.V12.Services.CustomerUserAccessInvitationServiceClientImpl.MutateCustomerUserAccessInvitation(MutateCustomerUserAccessInvitationRequest request, CallSettings callSettings) at .DAL.ExternalServices.GoogleAds.Services.GoogleAdsApiService.CancelInvitation(Int64 clientId) in C:\Repos****.DAL\ExternalServices\GoogleAds\Services\GoogleAdsManagerAccountApiService.cs:line 130 This exception was originally thrown at this call stack: [External Code] *.DAL.ExternalServices.GoogleAds.Services.GoogleAdsApiService.CancelInvitation(long) in GoogleAdsManagerAccountApiService.cs Client library version and API version: Google.Ads.GoogleAds.Core version: 2.1/0 Google.Ads.GoogleAds version: 14.2.0 Google.Ads.Gax 4.0.0 .NET version: Framework 4.8 Operating system ( Windows10) Request/Response Logs: Anything else we should know about your project / environment — Reply to this email directly, view it on GitHub <#510>, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABCOJCAOOHGZV2QXP7GBPLDW72XO5ANCNFSM6AAAAAAWVKL75Q . You are receiving this because you are subscribed to this thread.Message ID: @.>

@Savvelev if the issue still persists, pls send it anash@google.com. I'll forward it to the right aliases.