How to get all Modifying Users of a specific Revision - go

Follow up on Google Drive Rest API : How to get all Modifying Users of a specific Revision
It has been approximately 3 years, so I am not sure what the status is, but I thought I would ask again on the status.
I see that Google Drive API # https://developers.google.com/drive/api/v3/reference/revisions/get
should actually do exactly what has been asked here, but when I make a call to the API it returns null for LastModifyingUser
I am not sure if this is a work in progress API or I am doing something wrong, so any help would be appreciated.
Just to provide some reference, I am posting some basic code that is an addition to what can be found here... https://developers.google.com/drive/api/v3/quickstart/go
revision, err := srv.Revisions.Get(fileId, revisionId).Do() //fieldId and revisionId are fatched using proper calls
if err != nil {
log.Fatalf("Unable to retrieve revision: %v", err)
}
fmt.Println("Revision:")
fmt.Printf("%+v\n", revision.LastModifyingUser)

You want to retrieve the value of lastModifyingUser from Revisions.Get() using Drive API v3.
If my understanding is correct, how about adding the fields? At the default, the fields are id,mimeType,modifiedTime. So when you want to retrieve only values of lastModifyingUser, please modify as follows.
From:
revision, err := srv.Revisions.Get(fileId, revisionId).Do()
To:
revision, err := srv.Revisions.Get(fileID, revisionID).Fields("lastModifyingUser").Do()
Note:
In this modified script, it is supposes that when you run your current script, no error occurs.
If you want to add lastModifyingUser to the default values of id,mimeType,modifiedTime, please set the fields to id,mimeType,modifiedTime,lastModifyingUser.
Reference:
Revisions
If I misunderstand your question, I'm sorry.

Related

Add/delete members to M365 groups using MS Graph API with Golang

I'm trying to add and/or delete group members using graph/api with Golang
I am able to list members, or owners for groups, but not able to add to delete members.
//---CODE--- To list member of groups this code works an intended
cred, err := azidentity.NewClientSecretCredential("7c...","16...","sj...", nil,)
auth, err := a.NewAzureIdentityAuthenticationProviderWithScopes(cred, []string{"https://graph.microsoft.com/.default"})
requestAdapter, err := msgraphsdk.NewGraphRequestAdapter(auth)
graphClient := msgraphsdk.NewGraphServiceClient(requestAdapter)
result, err := graphClient.Users().Get()
// get member in 1 group
graphClientGroup := msgraphsdk.NewGraphServiceClient(requestAdapter)
r2, err := graphClientGroup.GroupsById("...group-id...").Members().Get()
When I try any variation for adding including as listed in MS docs:
https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0&tabs=go
requestBody := msgraphsdk.New()
requestBody.SetAdditionalData(map[string]interface{}{
"#odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/{id}",
}
graphClient.GroupsById(&groupId).MembersById(&directoryObjectId).Post(requestBody)
This code will not compile, other variations will run but not produce new group members or return an error.
For deleting members in M365 groups I tried to run code without success such as:
graphClient.GroupsById("groupId...").MembersById("memberID...").Ref().Delete()
No errors are returned and NO member deleted from group?
Thank you, for any guidance.
As mentioned in the documentation in GitHub:
The Microsoft Graph Go SDK is currently in Community Preview and breaking changes are expecting to happen to the SDK based on community's feedback.
The error with post() has been already reported. Details here
This issue is now fixed, as of 2022-05-31 v0.25.0

How do I access custom fields in an error?

Objective
Add a command to dropbox's CLI tool to get the shared link for the given path (file or folder).
The changes are here: github fork.
Background
The dropbox-go-sdk has a function that takes a path, and returns a new shared link, or returns an error containing the existing shared link.
I don't know how to use the error to extract the existing shared link.
Code
on github, and snippet here:
dbx := sharing.New(config)
res, err := dbx.CreateSharedLinkWithSettings(arg)
if err != nil {
switch e := err.(type) {
case sharing.CreateSharedLinkWithSettingsAPIError:
fmt.Printf("%v", e.EndpointError)
default:
return err
}
}
This prints the following:
&{{shared_link_already_exists} <nil> <nil>}found unknown shared link typeError: shared_link_already_exists/...
tracing:
CreateSharedLinkWithSettings --> CreateSharedLinkWithSettingsAPIError --> CreateSharedLinkWithSettingsError --> SharedLinkAlreadyExistsMetadata --> IsSharedLinkMetadata
IsSharedLinkMetadata contains the Url that I'm looking for.
More Info
The API docs point to CreateSharedLinkWithSettings, which should pass back the information in the error including the existing Url.
I struggle to understand how to deal with the error and extract the url from it.
The dbxcli has some code doing a similar operation, but again, not sure how it's working enough to apply it to the code I'm working on. Is it a Struct? Map? I don't know what this thing is called. There's some weird magic err.(type) stuff happening in the code. How do I access the data?
dbx := sharing.New(config)
res, err := dbx.CreateSharedLinkWithSettings(arg)
if err != nil {
switch e := err.(type) {
case sharing.CreateSharedLinkWithSettingsAPIError:
fmt.Printf("%v", e.EndpointError)
// type cast to the specific error and access the field you want.
settingsError := err.(sharing.CreateSharedLinkWithSettingsAPIError)
fmt.Println(settingsError.EndpointError.SharedLinkAlreadyExists.Metadata.Url)
default:
return err
}
}
The question was answered in the comments by #jimb. The answer is you access the fields like any other golang data structure - nothing special.
The errors I got when trying to access the fields were because the fields were not there.
The problem with the code was dependency issues. The code depends on an older version of the go-sdk and I referenced the latest version.
This question serves as a good explanation for how real golang programmers handle errors in their code with examples. I wasn't able to find this online, so I won't close the question.

How to get a list of all files in directory with Google Drive API(v3)

I have stuck with function that must to return me a list of all files from directory (in this case directory is "root"). When I call this function, it return me files that only I added with my program (this program also can upload files to Google Drive), not all files. And it also shows me files that I deleted :/. What I do wrong?
This function I was copied from Google Drive API Quickstart
service, err := getService()
if err != nil {
log.Fatalf("Unable to retrieve Drive client: %v", err)
}
r, err := service.Files.List().Q("'root' in parents").Do()
if err != nil {
log.Fatalf("Unable to retrieve files: %v", err)
}
fmt.Println("Files:")
if len(r.Files) == 0 {
fmt.Println("No files found.")
} else {
for _, i := range r.Files {
fmt.Printf("%v (%vs )\n", i.Name, i.Id)
}
}
You want to retrieve all files just under the root folder.
You want to achieve this using google-api-go-client with golang.
You have already been get and put values for Google Drive using Drive API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Issue and workaround:
From the situation of When I call this function, it return me files that only I added with my program (this program also can upload files to Google Drive), not all files., I thought that your scopes might include https://www.googleapis.com/auth/drive.file. When https://www.googleapis.com/auth/drive.file is used as the scope, only the files created by the application are retrieved.
In order to retrieve all files just under the root folder, please use the following scopes.
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.readonly
https://www.googleapis.com/auth/drive.metadata.readonly
https://www.googleapis.com/auth/drive.metadata.
If you want to retrieve only the file list, the scopes of .readonly can be used.
Modified script:
From your question, I could notice that you are using google-api-go-client with golang and Go Quickstart. In this case, how about the following modification?
If drive.DriveFileScope is included in the scopes, please modify as follows.
From:
config, err := google.ConfigFromJSON(b, drive.DriveFileScope)
To:
config, err := google.ConfigFromJSON(b, drive.DriveMetadataScope)
or
config, err := google.ConfigFromJSON(b, drive.DriveReadonlyScope)
If you want to also upload the file, please use drive.DriveScope.
Note:
When you modified the scopes, please remove the file of token.json of tokFile := "token.json". And please run the script and authorize again. By this, the modified scopes are reflected to the access token and refresh token. Please be careful this.
References:
google-api-go-client
Go Quickstart
Files: list
If I misunderstood your question and this was not the direction you want, I apologize.

Is it always safe to include err.Error() in the response?

Example:
err := Db.Find(&event, id).Error
if err != nil {
c.JSON(500, err.Error())
return
}
I'm worried that it might include sensitive information. Example: when connecting to a database and the db credentials are invalid, I'm worried that the error message might be something like: "invalid username: sample and password: xxx"
Effectively you answered your own question: you pointed out it may contain sensitive information which means it is not always safe to include them in responses visible to the users.
It may also contain information related to your implementation (e.g. package names, type names, call hierarchy), and also configuration data (e.g. server name, database name, user names etc.), potentially exposing private and sensitive architecture and business information.
Think about it: you're a package author and you create the error values (error messages) returned by your functions / methods. You create descriptive error messages describing why a requested function cannot complete normally, intended for the callers of that function/method (the developers), and not for the end users - who shouldn't know what's going on under the hood.
error.Error() messages are for the developers. They are also useful during testing. And they are indispensable for hunting down bugs. You should not show them to the users, instead log them to which you have access, and provide a more general or a user friendly error message to the users, ensuring them that the dev team has been notified and are looking into the problem. Showing original error messages may cause confusion in inexperienced users, and may raise security issues.
The best way is to write to the error log, And custom database error info for return.
like:
var (
ErrEventNotFound = "Event not found."
)
err := Db.Find(&event, id).Error
if err != nil {
// Log to file
c.JSON(500, ErrEventNotFound)
return
}

Use package file to write to Cloud Storage?

Golang provides the file package to access Cloud Storage.
The package's Create function requires the io.WriteCloser interface. However, I have not found a single sample or documentation showing how to actually save a file to Cloud Storage.
Can anybody help? Is there a higher level implementation of io.WriteCloser that would allow us to store files in Cloud Storage? Any sample code?
We've obviously tried to Google it ourselves but found nothing and now hope for the community to help.
It's perhaps true than the behavior is not well defined in the documentation.
If you check the code: https://code.google.com/p/appengine-go/source/browse/appengine/file/write.go#133
In each call to Write the data is sent to the cloud (line 139). So you don't need to save. (You should close the file when you're done, through.)
Anyway, I'm confused with your wording: "The package's Create function requires the io.WriteCloser interface." That's not true. The package's Create functions returns a io.WriteCloser, that is, a thingy you can write to and close.
yourFile, _, err := Create(ctx, "filename", nil)
// Check err != nil here.
defer func() {
err := yourFile.Close()
// Check err != nil here.
}()
yourFile.Write([]byte("This will be sent to the file immediately."))
fmt.Fprintln(yourFile, "This too.")
io.Copy(yourFile, someReader)
This is how interfaces work in Go. They just provide you with a set of methods you can call, hiding the actual implementation from you; and, when you just depend on a particular interface instead of a particular implementation, you can combine in multiple ways, as fmt.Fprintln and io.Copy do.

Resources