We are aware of the issue with the badge emails resending to everyone, we apologise for the inconvenience - learn more here.
Forum Discussion
dsoprea
11 months agoHelpful | Level 6
Folders that are visible from the SDK don't appear to be visible via the CLI
We have a "Full Dropbox" app installed on a team account. We're setting DROPBOX_MANAGE_APP_KEY and DROPBOX_MANAGE_APP_SECRET. I've also tried with DROPBOX_PERSONAL_APP_KEY and DROPBOX_PERSONAL_APP_SE...
- 11 months ago
Okay. Yes. That's what I was missing. I saw enough entries that has non-None team-member IDs that I missed that the one I was looking for had a None one.
Yes. That's fine. I'm not dealing with pagination given that this is a PoC that didn't require it.
Since this is a team-level folder, I've just enumerated the members and grabbed the first one:
# Get team-scoped resource dbxt = dropbox.dropbox_client.DropboxTeam( app_key=_DROPBOX_KEY, app_secret=_DROPBOX_SECRET, oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN) # Get members result = dbxt.team_members_list() # Grab the first member returned first_member_id = None for member in result.members: first_member_id = member.profile.team_member_id break assert \ first_member_id is not None, \ "No members found." # Get the namespace whose root we want to use r = dbxt.team_namespaces_list() namespace_id = None for namespace in r.namespaces: if namespace.name != 'ManagedIntake': continue namespace_id = namespace.namespace_id assert \ namespace_id is not None, \ "Could not find images namespace." # Get object scoped to the member and root-path above dbxtm = dbxt.as_user(first_member_id) path = dropbox.common.PathRoot.namespace_id(namespace_id) dbxtmp = dbxtm.with_path_root(path) result = dbxtmp.files_list_folder("") for entry in result.entries: print(entry.name)
So, that works, and works as desired.
How would the account-level access work? Since all of our apps would have to be team-scoped, are you just saying that removing the team-scopes will magically allow the app to have account -specific access? I had originally created a separate app for this and hadn't given it any team-scopes, but I was unable to even see this folder, presumably because it lives in the team space. Is that accurate?
Greg-DB
Dropbox Staff
By default, API calls to the Dropbox API operate in the "member folder" of the connected account, not the "team space". That means that by default, the contents of the team space will not be found. From the screenshot you shared, the "ManagedIntake" folder is in the team space.
API calls can be configured to operate in the "team space" instead though, in order to interact with files/folders in the team space, by using the "Dropbox-API-Path-Root" header as you mentioned. The official Dropbox SDKs, such as the official Dropbox Python SDK you're using in your code, do offer the ability to set that header if/when needed.
It looks like the dbxcli tool in particular though does not implement that header, and so cannot access the team space. It would default to operating inside the member folder, where the '/ManagedIntake' path doesn't refer to anything, accordingly resulting in the 'path/not_found' error.
dsoprea
11 months agoHelpful | Level 6
Okay, so rather than getting sucked into testing a PR that already professed to add that support or creating a PR of my own (because that PR had issues), I just reverted to using Python to have more control. I use a Team object to enumerate the namespaces, filter for the right one, and grab the namespace ID, and then set the path on the non-Team object:
# Get non-team scoped resource
dbx = dropbox.dropbox_client.Dropbox(
app_key=_DROPBOX_KEY,
app_secret=_DROPBOX_SECRET,
oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN)
# Get team-scoped resource
dbxt = dropbox.dropbox_client.DropboxTeam(
app_key=_DROPBOX_KEY,
app_secret=_DROPBOX_SECRET,
oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN)
r = dbxt.team_namespaces_list()
found = None
for namespace in r.namespaces:
if namespace.name != 'ManagedIntake':
continue
found = namespace
break
assert \
found is not None, \
"Could not find images namespace."
path = dropbox.common.PathRoot.namespace_id(found.namespace_id)
dbxtmp = dbx.with_path_root(path)
for entry in dbx.files_list_folder(""):
print(entry)
However, I'm getting the [normal] "using team keys to access a single account" error:
File "/home/dustin/.pyenv/versions/workflow_application/lib/python3.8/site-packages/dropbox/base.py", line 2145, in files_list_folder
r = self.request(
File "/home/dustin/.pyenv/versions/workflow_application/lib/python3.8/site-packages/dropbox/dropbox_client.py", line 326, in request
res = self.request_json_string_with_retry(host,
File "/home/dustin/.pyenv/versions/workflow_application/lib/python3.8/site-packages/dropbox/dropbox_client.py", line 476, in request_json_string_with_retry
return self.request_json_string(host,
File "/home/dustin/.pyenv/versions/workflow_application/lib/python3.8/site-packages/dropbox/dropbox_client.py", line 596, in request_json_string
self.raise_dropbox_error_for_resp(r)
File "/home/dustin/.pyenv/versions/workflow_application/lib/python3.8/site-packages/dropbox/dropbox_client.py", line 632, in raise_dropbox_error_for_resp
raise BadInputError(request_id, res.text)
dropbox.exceptions.BadInputError: BadInputError('7dbb18c6c1fb4a09bb58483a877d182c', 'Error in call to API function "files/list_folder": This API function operates on a single Dropbox account, but the OAuth 2 access token you provided is for an entire Dropbox Business team. Since your API app key has team member file access permissions, you can operate on a team member\'s Dropbox by providing the "Dropbox-API-Select-User" HTTP header or "select_user" URL parameter to specify the exact user <https://www.dropbox.com/developers/documentation/http/teams>.')
So, I switched to calling `as_user()` with the associated member ID on the Team object, setting the root on that, and then enumerating that, but I'm still getting the same error, which doesn't make sense to me:
# Get team-scoped resource
dbxt = dropbox.dropbox_client.DropboxTeam(
app_key=_DROPBOX_KEY,
app_secret=_DROPBOX_SECRET,
oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN)
r = dbxt.team_namespaces_list()
found = None
for namespace in r.namespaces:
if namespace.name != 'ManagedIntake':
continue
found = namespace
break
assert \
found is not None, \
"Could not find images namespace."
dbxtm = dbxt.as_user(found.team_member_id)
path = dropbox.common.PathRoot.namespace_id(found.namespace_id)
dbxtmp = dbxtm.with_path_root(path)
for entry in dbxtmp.files_list_folder(""):
print(entry)
Suggestions on what I could be missing?
- Greg-DB11 months agoDropbox Staff
The NamespaceMetadata.team_member_id is only returned for team member folders or app folders, not shared/team folders, so it wouldn't be returned for your "ManagedIntake". That means that you're not actually setting a value in as_user, resulting in that error. If you have a team-linked client like this, you'd need to get a relevant team member ID from elsewhere.
Also, note that if you use team_namespaces_list, you should implement team_namespaces_list_continue as well.
Alternatively, if you just want to connect to a particular account and access the files/folders via that account, you can disable any team scopes and get a new access token/refresh token without them. The access token/refresh token without the team scopes will be specific to the particular account (Business or not) and so will not require the additional header. You can find more information on scopes in the OAuth Guide. If you don't need to call any team endpoints (e.g., if you just need to call individual endpoints, such as via files_list_folder/files_list_folder_continue), I recommend this solution instead for simplicity and security.
Here's a simplified version of the code that should work to list a folder named "ManagedIntake" in the team space, when using a refresh token for a specific account, without any team scopes granted:
dbx = dropbox.Dropbox( app_key=_DROPBOX_KEY, app_secret=_DROPBOX_SECRET, oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN) root_info = dbx.users_get_current_account().root_info path = dropbox.common.PathRoot.root(root_info.root_namespace_id) dbx = dbx.with_path_root(path) for entry in dbx.files_list_folder("/ManagedIntake").entries: print(entry) # be sure to implement files_list_folder_continue as well
- dsoprea11 months agoHelpful | Level 6
Okay. Yes. That's what I was missing. I saw enough entries that has non-None team-member IDs that I missed that the one I was looking for had a None one.
Yes. That's fine. I'm not dealing with pagination given that this is a PoC that didn't require it.
Since this is a team-level folder, I've just enumerated the members and grabbed the first one:
# Get team-scoped resource dbxt = dropbox.dropbox_client.DropboxTeam( app_key=_DROPBOX_KEY, app_secret=_DROPBOX_SECRET, oauth2_refresh_token=_DROPBOX_REFRESH_TOKEN) # Get members result = dbxt.team_members_list() # Grab the first member returned first_member_id = None for member in result.members: first_member_id = member.profile.team_member_id break assert \ first_member_id is not None, \ "No members found." # Get the namespace whose root we want to use r = dbxt.team_namespaces_list() namespace_id = None for namespace in r.namespaces: if namespace.name != 'ManagedIntake': continue namespace_id = namespace.namespace_id assert \ namespace_id is not None, \ "Could not find images namespace." # Get object scoped to the member and root-path above dbxtm = dbxt.as_user(first_member_id) path = dropbox.common.PathRoot.namespace_id(namespace_id) dbxtmp = dbxtm.with_path_root(path) result = dbxtmp.files_list_folder("") for entry in result.entries: print(entry.name)
So, that works, and works as desired.
How would the account-level access work? Since all of our apps would have to be team-scoped, are you just saying that removing the team-scopes will magically allow the app to have account -specific access? I had originally created a separate app for this and hadn't given it any team-scopes, but I was unable to even see this folder, presumably because it lives in the team space. Is that accurate?
- Greg-DB11 months agoDropbox Staff
Yes, when an app doesn't use team scopes, it gets connected to a specific account, not the entire team. When an app uses team scopes, it gets connected to the entire team, not just a specific account.
So, when an app doesn't use team scopes and is connected to a specific account, there is only one relevant account and so you don't need to specify a member ID using as_user.
Either way, in order to access the team space, you do need to use with_path_root. You can use that whether or not that app uses team scopes, as long as the app is registered for "full Dropbox" access (and not "app folder" access).
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
5,877 PostsLatest Activity: 12 months agoIf you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X or Facebook.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!