Search code examples
c#.net-coregoogle-apigoogle-workspace

Using the Google Workspace API to get the storage used by a user


I would like to query the Google Workspace API in order to obtain the Storage Consumed by a user. I am using .NET 7 C# to access the Google Directory and GMAIL configuration for users. This connects to a service application and uses impersonation, and this is all working correctly. I have added DriveService.Scope.Drive scope to my Scopes Array and this Scope is enabled in my Google API Service. I am calling the following function:

 public void GetUserStorageUsage(string emailAddress)
{
    // Create Directory API service.
    DriveService driveService = new DriveService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = GetOAuthServiceAccountCredential(emailAddress),
        ApplicationName = ApplicationName
    });



    var x = driveService.About.Get();
    if(x !=null)
    {
        var z = x.Execute();
    }

}

and it is throwing the following exception from the Google.Apis package:

Google.GoogleApiException
  HResult=0x80131500
  Source=Google.Apis
  StackTrace:
   at Google.Apis.Requests.ClientServiceRequest`1.<ParseResponse>d__38.MoveNext() in Google.Apis.Requests\ClientServiceRequest.cs:line 157
   at Google.Apis.Requests.ClientServiceRequest`1.Execute() in Google.Apis.Requests\ClientServiceRequest.cs:line 103

I added a break point inside the ClientServiceRequest.cs so that I could look at the HttpResponseMessage and in calling:

https://www.googleapis.com/drive/v3/about

I am receiving a 400 Status Code with a reason phrase of "Bad Request"

Perhaps my approach is wrong? If anyone has insight I would appreciate it. I have little luck finding examples of obtaining Google Workspace User Storage Usage.

Here is the impersonation function

public ServiceAccountCredential GetOAuthServiceAccountCredential(String IpersonatedUser)
{
           ServiceAccountCredential credential;

           using (FileStream? stream = new FileStream(Filename , FileMode.Open, FileAccess.Read))
           {
               credential =
                 GoogleCredential
                   .FromStream(stream)
                   .CreateScoped(Scopes)
                   .CreateWithUser(IpersonatedUser)
                   .UnderlyingCredential as ServiceAccountCredential;
           }
           //credential.User = IpersonatedUser;

           //FieldInfo userField = typeof(ServiceAccountCredential).GetField("User", BindingFlags.NonPublic | BindingFlags.Instance);
           //userField.SetValue(credential, IpersonatedUser);

           return credential;
}

And here are the scopes:

private String[] Scopes = {
    DirectoryService.Scope.AdminDirectoryCustomer,
    DirectoryService.Scope.AdminDirectoryDomain,
    DirectoryService.Scope.AdminDirectoryGroup,
    DirectoryService.Scope.AdminDirectoryGroupMember,
    DirectoryService.Scope.AdminDirectoryOrgunit,
    DirectoryService.Scope.AdminDirectoryUser,
    DirectoryService.Scope.AdminDirectoryUserAlias,
    GmailService.Scope.GmailSettingsBasic,
    GmailService.Scope.GmailSettingsSharing,
    DriveService.Scope.Drive
};

Thanks


Solution

  • This is my drive service account sample

    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
    
    Console.WriteLine("Google drive api service account example, workspace delegation");
    
    const string PathToServiceAccountKeyFile = @"C:\Development\FreeLance\GoogleSamples\Credentials\workspaceserviceaccount.json";
    
    var credential = GoogleCredential.FromFile(PathToServiceAccountKeyFile)
        .CreateWithUser("[email protected]")  // delegate to user on workspace.
        .CreateScoped(new[] {DriveService.ScopeConstants.Drive});
    
    // Create the  Drive service.
    var service = new DriveService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential
    });
    
    var result = await service.Files.List().ExecuteAsync();
    
    foreach (var file in result.Files)
    {
        Console.WriteLine(file.Id);
    }
    

    about.get

    about .get requires that you pass the fields var

    var request = service.About.Get();
        request.Fields = "*";
    var aboutResponse = await request.ExecuteAsync();    
    
    var json = JsonSerializer.Serialize(aboutResponse);
    Console.WriteLine(json);