Class DropboxApiCommands
This class mirrors TrueFoundryApiCommands: every method opens a fresh
GrouperHttpClient, attaches bearer authentication, POSTs a JSON body, tracks per-command
timing via GrouperProvisioner.incrementCommandsCallsStats(String, int, long), and parses
the JSON response with the GrouperUtil.jsonJackson* helpers. The Dropbox DAO and the
provisioner tests call the public static methods here.
Auth difference from TrueFoundry. TrueFoundry stores a JSON blob of two tokens in the
accessTokenPassword; Dropbox uses a single, plain bearer token, so
attachAuthentication(GrouperHttpClient, String) reads accessTokenPassword as the
literal token string with no JSON parse. The base URL comes from
grouper.wsBearerToken.<configId>.endpoint (the mock service path in tests,
https://api.dropboxapi.com in prod) -- never hardcoded.
Dropbox conventions. Every Team API call is a POST with a JSON object body (use
"{}" when there are no arguments). Unions are encoded with a ".tag" discriminator.
Long-running write operations (group delete, group member add/remove, member add/remove) may
return an async_job_id instead of completing inline; this layer polls the matching
.../job_status/... endpoint until the job reports {".tag":"complete"} (see
pollIfAsync(java.util.Map<java.lang.String, java.lang.Object>, java.lang.String, com.fasterxml.jackson.databind.JsonNode, java.lang.String)). The mock returns synchronous complete results, so polling is a
no-op under test but is required in production.
-
Field Summary
FieldsModifier and TypeFieldDescriptionthe bearer token header carries secrets, so never log itstatic GrouperLoaderConfigloader config, used to resolve endpoint + token by configId -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic voidaddDropboxGroupMembers(String configId, String groupId, List<DropboxMembership> memberships) Add members to a Dropbox group via POST /2/team/groups/members/add.static DropboxGroupcreateDropboxGroup(String configId, DropboxGroup dropboxGroup) Create a Dropbox team group via POST /2/team/groups/create.static DropboxUsercreateDropboxUser(String configId, DropboxUser dropboxUser) Create (invite) a Dropbox team member via POST /2/team/members/add_v2.static voiddeleteDropboxGroup(String configId, String groupId) Delete a Dropbox team group via POST /2/team/groups/delete.static booleanCheck whether a value is in the ignore set (case-insensitive).static voidManual integration entry point.parseIgnoreSet(String commaSeparated) Parse a comma-separated ignore string into a lowercase set for case-insensitive matching.static voidrecoverDropboxUser(String configId, String email) Recover a removed Dropbox team member within the 7-day recovery window via POST /2/team/members/recover, selecting the member by email.static voidremoveDropboxGroupMembers(String configId, String groupId, List<String> teamMemberIds) Remove members from a Dropbox group via POST /2/team/groups/members/remove.static voidremoveDropboxUser(String configId, String teamMemberId, boolean wipeData, boolean keepAccount) Remove a Dropbox member from the team via POST /2/team/members/remove.retrieveAdminRoleNameToId(String configId) Return the cached admin-role name -> role_id map for a config.retrieveAdminRoleNameToId(String configId, String teamMemberId) Return the admin-role name -> role_id catalog, fetching it authoritatively from POST /2/team/members/list_member_roles for the given member.static DropboxGroupretrieveDropboxGroup(String configId, String groupId) Retrieve a single Dropbox group by its native group_id via POST /2/team/groups/get_info.static List<DropboxMembership>retrieveDropboxGroupMemberships(String configId, String groupId) Retrieve all memberships of a Dropbox group via POST /2/team/groups/members/list, paging with /2/team/groups/members/list/continue untilhas_moreis false.static List<DropboxGroup>retrieveDropboxGroups(String configId) Retrieve all Dropbox team groups via POST /2/team/groups/list, paging with /2/team/groups/list/continue untilhas_moreis false.static DropboxUserretrieveDropboxUser(String configId, String selectorTag, String selectorValue) Retrieve a single Dropbox member via POST /2/team/members/get_info_v2 using a UserSelectorArg union.static List<DropboxUser>retrieveDropboxUsers(String configId) Retrieve all Dropbox team members via POST /2/team/members/list_v2, paging with /2/team/members/list/continue_v2 untilhas_moreis false.static voidsetDropboxAdminRoles(String configId, String teamMemberId, List<String> roleIds) Set a Dropbox member's admin roles via POST /2/team/members/set_admin_permissions_v2.static voidsuspendDropboxUser(String configId, String teamMemberId) Suspend a Dropbox team member (deactivate; the account stays on the team but the member loses access) via POST /2/team/members/suspend. wipe_data is false so the member's files are retained for when they are unsuspended.static voidunsuspendDropboxUser(String configId, String teamMemberId) Unsuspend (reactivate) a previously suspended Dropbox team member via POST /2/team/members/unsuspend.static DropboxGroupupdateDropboxGroup(String configId, DropboxGroup dropboxGroup) Update a Dropbox team group via POST /2/team/groups/update.static DropboxUserupdateDropboxUser(String configId, DropboxUser dropboxUser, Set<String> fieldNamesToSet) Update a Dropbox member's profile via POST /2/team/members/set_profile_v2.
-
Field Details
-
doNotLogHeaders
the bearer token header carries secrets, so never log it -
grouperLoaderConfig
loader config, used to resolve endpoint + token by configId
-
-
Constructor Details
-
DropboxApiCommands
public DropboxApiCommands()
-
-
Method Details
-
retrieveAdminRoleNameToId
Return the cached admin-role name -> role_id map for a config. Dropbox has no standalone roles-list endpoint, so the catalog is populated as a side effect ofretrieveDropboxUsers(String)(which harvests each member'sroles[]). If the cache is empty, a member read is triggered once to populate it.- Parameters:
configId- external system config id- Returns:
- a copy of the admin-role name -> role_id map (possibly empty, never null)
-
retrieveAdminRoleNameToId
Return the admin-role name -> role_id catalog, fetching it authoritatively from POST /2/team/members/list_member_roles for the given member. Dropbox's list_member_roles returns the full set of assignable admin roles for the team (not just the member's current roles), so this works even on a fresh team where no member yet has an admin role -- unlike harvesting roles[] from member reads. Results are merged into the per-config cache.- Parameters:
configId- external system config idteamMemberId- a native team_member_id to scope the list_member_roles call- Returns:
- a copy of the admin-role name -> role_id map (possibly empty, never null)
-
retrieveDropboxGroups
Retrieve all Dropbox team groups via POST /2/team/groups/list, paging with /2/team/groups/list/continue untilhas_moreis false.- Parameters:
configId- external system config id- Returns:
- the list of DropboxGroup objects
-
retrieveDropboxGroup
Retrieve a single Dropbox group by its native group_id via POST /2/team/groups/get_info. The response is an array of GroupsGetInfoItem; a not-found id yields anid_not_foundentry, for which null is returned.- Parameters:
configId- external system config idgroupId- the native Dropbox group_id (e.g. "g:abc123")- Returns:
- the DropboxGroup, or null if not found
-
createDropboxGroup
Create a Dropbox team group via POST /2/team/groups/create. The response is a GroupFullInfo carrying the assigned native group_id.- Parameters:
configId- external system config iddropboxGroup- the group to create (must have name set)- Returns:
- the created DropboxGroup with id populated
-
updateDropboxGroup
Update a Dropbox team group via POST /2/team/groups/update. The group is selected by group_id; only the supplied new_* fields are changed. The response is a GroupFullInfo.- Parameters:
configId- external system config iddropboxGroup- the group to update (must have id set)- Returns:
- the updated DropboxGroup
-
deleteDropboxGroup
Delete a Dropbox team group via POST /2/team/groups/delete. The response is a LaunchEmptyResult, which may be asynchronous; this method polls /2/team/groups/job_status/get until the delete completes.- Parameters:
configId- external system config idgroupId- the native Dropbox group_id to delete
-
retrieveDropboxGroupMemberships
public static List<DropboxMembership> retrieveDropboxGroupMemberships(String configId, String groupId) Retrieve all memberships of a Dropbox group via POST /2/team/groups/members/list, paging with /2/team/groups/members/list/continue untilhas_moreis false. Each GroupMemberInfo is converted into a DropboxMembership (group_id + team_member_id + access_type).- Parameters:
configId- external system config idgroupId- the native Dropbox group_id- Returns:
- the list of memberships
-
addDropboxGroupMembers
public static void addDropboxGroupMembers(String configId, String groupId, List<DropboxMembership> memberships) Add members to a Dropbox group via POST /2/team/groups/members/add. Each membership becomes a{"user":UserSelectorArg,"access_type":{".tag":..}}entry. The response is a GroupMembersChangeResult which may carry anasync_job_id; this method polls /2/team/groups/job_status/get to completion.- Parameters:
configId- external system config idgroupId- the native Dropbox group_idmemberships- the memberships to add (team_member_id + access_type)
-
removeDropboxGroupMembers
public static void removeDropboxGroupMembers(String configId, String groupId, List<String> teamMemberIds) Remove members from a Dropbox group via POST /2/team/groups/members/remove. The response is a GroupMembersChangeResult which may carry anasync_job_id; this method polls /2/team/groups/job_status/get to completion.- Parameters:
configId- external system config idgroupId- the native Dropbox group_idteamMemberIds- the native team_member_ids to remove
-
retrieveDropboxUsers
Retrieve all Dropbox team members via POST /2/team/members/list_v2, paging with /2/team/members/list/continue_v2 untilhas_moreis false. As a side effect, each member'sroles[]array is harvested into the admin-role catalog cache (seeretrieveAdminRoleNameToId(String)).- Parameters:
configId- external system config id- Returns:
- the list of DropboxUser objects
-
retrieveDropboxUser
public static DropboxUser retrieveDropboxUser(String configId, String selectorTag, String selectorValue) Retrieve a single Dropbox member via POST /2/team/members/get_info_v2 using a UserSelectorArg union.selectorTagis the union tag (external_id,email, orteam_member_id) andselectorValueis the matching value. Returns null when the member is not found (id_not_found).- Parameters:
configId- external system config idselectorTag- the union discriminator (external_id | email | team_member_id)selectorValue- the value to match- Returns:
- the DropboxUser, or null if not found
-
createDropboxUser
Create (invite) a Dropbox team member via POST /2/team/members/add_v2. The response is either an inline{".tag":"complete","complete":[MemberAddV2Result]}or a deferred{".tag":"async_job_id",..}; in the deferred case this method polls /2/team/members/add/job_status/get_v2 and reads the completed result from the terminal response.- Parameters:
configId- external system config iddropboxUser- the member to create (must have email set)- Returns:
- the created DropboxUser with team_member_id populated, or null if the result is unusable
-
updateDropboxUser
public static DropboxUser updateDropboxUser(String configId, DropboxUser dropboxUser, Set<String> fieldNamesToSet) Update a Dropbox member's profile via POST /2/team/members/set_profile_v2. The member is selected by team_member_id; only the supplied field names are changed. The response is a TeamMemberInfoV2 ({"profile":..}).- Parameters:
configId- external system config iddropboxUser- the member with updated fields (must have id set)fieldNamesToSet- the field names to update, or null for all- Returns:
- the updated DropboxUser
-
removeDropboxUser
public static void removeDropboxUser(String configId, String teamMemberId, boolean wipeData, boolean keepAccount) Remove a Dropbox member from the team via POST /2/team/members/remove. The response is a LaunchEmptyResult which may be asynchronous; this method polls /2/team/members/remove/job_status/get to completion.- Parameters:
configId- external system config idteamMemberId- the native team_member_id to removewipeData- whether to wipe the member's data on removalkeepAccount- whether to convert the account to a free Basic account (keep) rather than delete it
-
suspendDropboxUser
Suspend a Dropbox team member (deactivate; the account stays on the team but the member loses access) via POST /2/team/members/suspend. wipe_data is false so the member's files are retained for when they are unsuspended.- Parameters:
configId- external system config idteamMemberId- the native team_member_id to suspend
-
unsuspendDropboxUser
Unsuspend (reactivate) a previously suspended Dropbox team member via POST /2/team/members/unsuspend.- Parameters:
configId- external system config idteamMemberId- the native team_member_id to unsuspend
-
setDropboxAdminRoles
Set a Dropbox member's admin roles via POST /2/team/members/set_admin_permissions_v2. An emptyroleIdslist demotes the member to member_only (no admin rights). Role ids are resolved by the caller viaretrieveAdminRoleNameToId(String).- Parameters:
configId- external system config idteamMemberId- the native team_member_idroleIds- the Dropbox role ids to assign (empty for member_only)
-
recoverDropboxUser
Recover a removed Dropbox team member within the 7-day recovery window via POST /2/team/members/recover, selecting the member by email. Used bycreateDropboxUser(java.lang.String, edu.internet2.middleware.grouper.app.dropbox.DropboxUser)when a re-add hits theuser_already_on_teamrecoverable conflict. Throws if recovery fails -- e.g. the account was invited-but-never-accepted, or is outside the recovery window (the caller then surfaces a normal provisioning failure).- Parameters:
configId- external system config idemail- the member email to recover
-
parseIgnoreSet
Parse a comma-separated ignore string into a lowercase set for case-insensitive matching.- Parameters:
commaSeparated- the comma-separated string (may be null or blank)- Returns:
- the set of lowercase trimmed values, or null if the input is blank/empty
-
isIgnored
Check whether a value is in the ignore set (case-insensitive).- Parameters:
value- the value to checkignoreSet- the set of lowercase values to ignore- Returns:
- true if the value should be ignored
-
main
Manual integration entry point. Requires grouper-loader.properties configured with a "dropboxProd" WsBearerToken external system. Intended for hand-running against a real tenant; the automated tests use the mock service instead.- Parameters:
args- unused
-