Class DropboxMockServiceHandler
This handler mirrors TrueFoundryMockServiceHandler: it stands in for the real Dropbox
service behind the /mockServices/dropbox/... servlet path, backs the API onto three mock
tables (mock_dropbox_group, mock_dropbox_user, mock_dropbox_membership)
via Hibernate/GcDbAccess, and returns JSON shaped exactly as DropboxApiCommands
sends and expects.
Protocol notes. Every Dropbox Team API call is an HTTP POST with a JSON object body and
a JSON response; unions carry a ".tag" discriminator. Unlike the real service (which can
defer long-running writes behind an async_job_id and a .../job_status/... poll),
this mock always completes synchronously: deletes/removes return
{".tag":"complete"} and members/add_v2 returns
{".tag":"complete","complete":[...]} with no async_job_id. That keeps the tests off
the polling path in DropboxApiCommands.pollIfAsync(java.util.Map<java.lang.String, java.lang.Object>, java.lang.String, com.fasterxml.jackson.databind.JsonNode, java.lang.String).
Auth difference from TrueFoundry. TrueFoundry stores a JSON blob of two tokens in
accessTokenPassword and accepts either; Dropbox uses a single plain bearer token, so
checkAuthorization(MockServiceRequest) compares the Authorization: Bearer value
to the stored accessTokenPassword string directly, with no JSON parse.
Admin roles. Dropbox exposes no "list all roles" endpoint, so this mock publishes a
fixed catalog of the 8 built-in admin roles, each mapped to a synthetic, deterministic
role_id of "pid_dbtmr:" + lowercase(name) (see roleIdForName(String) /
roleNameForRoleId(String)). A member's current role is stored as a single name in
mock_dropbox_user.admin_role (null == member_only). The roles[] array emitted by
member reads is harvested by DropboxApiCommands to learn the name -> role_id mapping it
needs for set_admin_permissions_v2.
-
Field Summary
FieldsModifier and TypeFieldDescriptionthe bearer token header carries the secret, so never log itstatic final Stringthe access token the mock /oauth2/token endpoint issues (and checkAuthorization accepts) -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidcheckAuthorization(MockServiceRequest mockServiceRequest) Validate theAuthorization: Bearer <token>header against the configured Dropbox bearer token.static voidLazily create the three Dropbox mock tables (group, user, membership) if any is missing.voidgroupsCreate(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/create.voidgroupsDelete(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/delete.voidgroupsGetInfo(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/get_info.voidgroupsList(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/list (and /list/continue).voidgroupsMembersAdd(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/add.voidgroupsMembersList(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/list (and /list/continue).voidgroupsMembersRemove(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/remove.voidgroupsUpdate(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/update.voidhandleRequest(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) Route the incoming mock request.voidmembersAddV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/add_v2.voidmembersGetInfoV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/get_info_v2.voidmembersListMemberRoles(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/list_member_roles.voidmembersListV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/list_v2 (and /list/continue_v2).voidmembersRecover(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/recover.voidmembersRemove(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/remove.voidmembersSetAdminPermissionsV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/set_admin_permissions_v2.voidmembersSetProfileV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/set_profile_v2.voidmembersSuspend(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/suspend.voidmembersUnsuspend(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/unsuspend.voidoauth2Token(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /oauth2/token (refresh-token grant).static StringroleIdForName(String roleName) Map an admin-role NAME to its fixed synthetic role_id ("pid_dbtmr:" + lowercase(name)).static StringroleNameForRoleId(String roleId) Reverse-map a synthetic role_id back to its admin-role NAME by scanning the fixed 8-role catalog.
-
Field Details
-
doNotLogHeaders
the bearer token header carries the secret, so never log it -
MOCK_OAUTH_ACCESS_TOKEN
the access token the mock /oauth2/token endpoint issues (and checkAuthorization accepts)- See Also:
-
-
Constructor Details
-
DropboxMockServiceHandler
public DropboxMockServiceHandler()
-
-
Method Details
-
doNotLogHeaders
- Overrides:
doNotLogHeadersin classMockServiceHandler
-
doNotLogParameters
- Overrides:
doNotLogParametersin classMockServiceHandler
-
ensureDropboxMockTables
public static void ensureDropboxMockTables()Lazily create the three Dropbox mock tables (group, user, membership) if any is missing. MirrorsTrueFoundryMockServiceHandler.ensureTrueFoundryMockTables. -
checkAuthorization
Validate theAuthorization: Bearer <token>header against the configured Dropbox bearer token. Dropbox stores a single plain token inaccessTokenPassword(no JSON blob like TrueFoundry), so the comparison is a direct string equals.- Parameters:
mockServiceRequest- the incoming request
-
oauth2Token
public void oauth2Token(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /oauth2/token (refresh-token grant). Simulates the Dropbox OAuth2 token endpoint: ignores the form body (the real endpoint validates grant_type/refresh_token/client_id/client_secret) and returns a fixed short-lived access token with a 4h expiry. No bearer auth -- the real token endpoint authenticates via the client credentials in the body. -
groupsList
public void groupsList(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/list (and /list/continue). Return every group as a GroupSummary. Paging is simulated as a single page:has_moreis always false, so the/continueendpoint (which shares this method) simply returns the same full set with no further pages. -
groupsGetInfo
public void groupsGetInfo(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/get_info. Body is a GroupsSelector union{".tag":"group_ids","group_ids":[..]}. Returns an ARRAY of GroupsGetInfoItem: each known id yields{".tag":"group_info", ...GroupFullInfo with members[]}, each unknown id yields{".tag":"id_not_found","id_not_found":id}. -
groupsCreate
public void groupsCreate(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/create. Body = DropboxGroup.toCreateJson() (group_name, optional group_external_id, group_management_type union). Assign a native group_id of"g:" + uuid, persist, and return the new group's GroupFullInfo. -
groupsUpdate
public void groupsUpdate(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/update. Body carries a GroupSelector by group_id plus the new_* fields. Apply new_group_name / new_group_external_id and return the updated GroupFullInfo. -
groupsDelete
public void groupsDelete(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/delete. Body{".tag":"group_id","group_id":".."}. Delete the group and all of its memberships, then return a SYNCHRONOUS LaunchEmptyResult{".tag":"complete"}(the mock never defers behind an async_job_id). -
groupsMembersAdd
public void groupsMembersAdd(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/add. Body carries a GroupSelector plus a members[] array of{"user":UserSelectorArg,"access_type":{".tag":..}}. Insert a membership row per entry (idempotent on group_id + team_member_id) and return a GroupMembersChangeResult{"group_info":GroupFullInfo}with no async_job_id. -
groupsMembersRemove
public void groupsMembersRemove(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/remove. Body carries a GroupSelector plus a users[] array of UserSelectorArg. Delete the matching membership rows and return a GroupMembersChangeResult. -
groupsMembersList
public void groupsMembersList(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/groups/members/list (and /list/continue). Return the group's members as GroupMemberInfo objects. Single-page mock: has_more is always false. -
membersListV2
public void membersListV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/list_v2 (and /list/continue_v2). Return every member as{"profile":TeamMemberProfile,"roles":[TeamMemberRole]}. Single-page mock: has_more false. -
membersGetInfoV2
public void membersGetInfoV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/get_info_v2. Body{"members":[UserSelectorArg]}where each selector tag is external_id | email | team_member_id. Return{"members_info":[{".tag":"member_info","profile":..,"roles":..}]}; an unknown selector yields{".tag":"id_not_found"}. -
membersAddV2
public void membersAddV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/add_v2. Body{"new_members":[..],"force_async":false}; each entry carries member_email / member_given_name / member_surname / member_external_id. Assign a native team_member_id of"dbmid:" + uuidand an account_id, set status active, persist, and return a SYNCHRONOUS{".tag":"complete","complete":[{".tag":"success","success":{"profile":..,"role":..}}]}. -
membersSetProfileV2
public void membersSetProfileV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/set_profile_v2. Body carries a UserSelectorArg plus new_email / new_external_id / new_given_name / new_surname. Apply by team_member_id and return the updated TeamMemberInfoV2{"profile":TeamMemberProfile}. -
membersRemove
public void membersRemove(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/remove. Body{"user":UserSelectorArg,"wipe_data":..,"keep_account":..}. Hard-delete the member (and all of their memberships) and return a SYNCHRONOUS LaunchEmptyResult{".tag":"complete"}. -
membersRecover
public void membersRecover(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/recover. Body{"user":{".tag":"email","email":..}}. Restore a removed-but-recoverable member; the mock has no separate removed state, so it simply finds the member by selector and confirms it active, returning an empty object. A member not found returns the not-found error (the real API returns 409 user_unrecoverable / user_not_found). -
membersSuspend
public void membersSuspend(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/suspend. Body{"user":UserSelectorArg,"wipe_data":..}. Set the member's status to suspended and return an empty object{}(the real API replies 200 with no body). -
membersUnsuspend
public void membersUnsuspend(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/unsuspend. Body{"user":UserSelectorArg}. Set the member's status back to active and return an empty object{}. -
membersSetAdminPermissionsV2
public void membersSetAdminPermissionsV2(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/set_admin_permissions_v2. Body{"user":UserSelectorArg,"new_roles":[role_id,..]}. Map the (first) role_id back to its admin-role NAME via the fixed catalog and store it inadmin_role; an empty new_roles list clears the role (member_only == null). Return{"team_member_id":..}. -
membersListMemberRoles
public void membersListMemberRoles(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) POST /2/team/members/list_member_roles. Body{"team_member_id":".."}. Returns the full set of ASSIGNABLE admin roles for the team as{"roles":[TeamMemberRole]}-- i.e. the complete 8-role catalog, NOT just the member's current role. This mirrors the real Dropbox endpoint (which lists roles a member can be assigned) and is what lets a caller resolve a role NAME to a role_id on a fresh team where no member yet holds a role. -
roleIdForName
Map an admin-role NAME to its fixed synthetic role_id ("pid_dbtmr:" + lowercase(name)).- Parameters:
roleName- the admin-role name- Returns:
- the synthetic role_id
-
roleNameForRoleId
Reverse-map a synthetic role_id back to its admin-role NAME by scanning the fixed 8-role catalog. Returns null when the id matches no known role.- Parameters:
roleId- the synthetic role_id- Returns:
- the admin-role name, or null
-
handleRequest
public void handleRequest(MockServiceRequest mockServiceRequest, MockServiceResponse mockServiceResponse) Route the incoming mock request. All Dropbox Team API calls are POSTs whose path after/mockServices/dropboxis a fixed endpoint (e.g./2/team/groups/list). The path segments are joined and dispatched to the matching handler method, mirroring the TrueFoundry mock's POST-plus-path routing style.- Specified by:
handleRequestin classMockServiceHandler- Parameters:
mockServiceRequest- the requestmockServiceResponse- the response
-