diff --git a/src/GamCommands.txt b/src/GamCommands.txt index ebeb7c79..834428b9 100644 --- a/src/GamCommands.txt +++ b/src/GamCommands.txt @@ -7058,6 +7058,7 @@ gam move drivefile [newfilename ]] [copysubfolderinheritedpermissions []] [copysubfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders] + [movefilepermissions []] [excludepermissionsfromdomains|includepermissionsfromdomains ] (mappermissionsemail )* [mappermissionsemailfile endcsv] (mappermissionsdomain )* diff --git a/src/GamUpdate.txt b/src/GamUpdate.txt index 83844a5b..ba40dd43 100644 --- a/src/GamUpdate.txt +++ b/src/GamUpdate.txt @@ -4,6 +4,11 @@ Added options `isdisabled []`, `disabledafter ` and `disable to `gam print users`. These options along with `issuspended []` and `isarchived []` are useful when identifying users to deprovision. +Added option `movefilepermissions []]` to `gam move drivefile` that, when False, +causes GAM to remove ACLs from a file before moving it; this will be most useful when moving files to +Shared Drives so that only the Shared Drive ACls apply. When not specified or set True, file permissions +are not removed; this is the current GAM behavior. + 7.44.03 Added `writerwithoutprivateaccess` to ``; this will become effective 2026-06-29. diff --git a/src/gam/__init__.py b/src/gam/__init__.py index 4decb6e9..13c38cc9 100755 --- a/src/gam/__init__.py +++ b/src/gam/__init__.py @@ -63103,6 +63103,7 @@ def initCopyMoveOptions(copyCmd): 'copyTopFolderNonInheritedPermissions': COPY_NONINHERITED_PERMISSIONS_ALWAYS, 'copySubFolderNonInheritedPermissions': COPY_NONINHERITED_PERMISSIONS_ALWAYS, 'noCopyNonInheritedPermissions': COPY_NONINHERITED_PERMISSIONS_NEVER, + 'moveFilePermissions': True, 'excludePermissionsFromDomains': set(), 'includePermissionsFromDomains': set(), 'mapPermissionsEmails': {}, @@ -63222,6 +63223,8 @@ def getCopyMoveOptions(myarg, copyMoveOptions): copyMoveOptions['mergeWithParent'] = False elif myarg == 'createshortcutsfornonmovablefiles': copyMoveOptions['createShortcutsForNonmovableFiles'] = getBoolean() + elif myarg == 'movefilepermissions': + copyMoveOptions['moveFilePermissions'] = getBoolean() else: return False # Copy arguments @@ -64553,20 +64556,24 @@ def _updateMoveFilePermissions(drive, user, i, count, return [Ent.USER, user, entityType, title, Ent.PERMISSION, permstr] def isPermissionDeletable(kvList, permission): - domain = '' - if copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains']: + if not copyMoveOptions['moveFilePermissions']: + notMovedMessage = 'movefilepermissions false' + elif permission.pop('deleted', False): + notMovedMessage = f"{permission['type']} {permission['emailAddress']} deleted" + elif copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains']: + domain = '' if permission['type'] in {'group', 'user'}: atLoc = permission.get('emailAddress', '').find('@') if atLoc > 0: domain = permission['emailAddress'][atLoc+1:].lower() elif permission['type'] == 'domain': domain = permission.get('domain', '').lower() - if domain and domain in copyMoveOptions['excludePermissionsFromDomains']: - notMovedMessage = f'domain {domain} excluded' - elif domain and copyMoveOptions['includePermissionsFromDomains'] and domain not in copyMoveOptions['includePermissionsFromDomains']: - notMovedMessage = f'domain {domain} not included' - elif permission.pop('deleted', False): - notMovedMessage = f"{permission['type']} {permission['emailAddress']} deleted" + if domain and domain in copyMoveOptions['excludePermissionsFromDomains']: + notMovedMessage = f'domain {domain} excluded' + elif domain and copyMoveOptions['includePermissionsFromDomains'] and domain not in copyMoveOptions['includePermissionsFromDomains']: + notMovedMessage = f'domain {domain} not included' + else: + return False else: return False deleteSourcePerms[permission['id']] = permission.copy() @@ -64745,6 +64752,7 @@ def _recursiveUpdateMovePermissions(drive, user, i, count, # [copypermissionroles ] # [copypermissiontypes ] # [synctopfoldernoniheritedpermissions []] [syncsubfoldernoninheritedpermissions []] +# [movefilepermissions []] # [excludepermissionsfromdomains|includepermissionsfromdomains ] # (mappermissionsemail )* [mappermissionsemailfile endcsv] # (mappermissionsdomain )* @@ -65117,7 +65125,8 @@ def moveDriveFile(users): verifyOrganizer = getBoolean() else: unknownArgumentExit() - updateMovePermissions = (copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains'] or + updateMovePermissions = ((not copyMoveOptions['moveFilePermissions']) or + copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains'] or copyMoveOptions['mapPermissionsDomains'] or copyMoveOptions['mapPermissionsEmails']) i, count, users = getEntityArgument(users)