Compare commits

..

6 Commits

Author SHA1 Message Date
Ross Scroggs
bdce13e97b Removed drive_v3_native_names from gam.cfg
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-27 09:17:44 -07:00
Ross Scroggs
9c4a17e12c Update gam.cfg.md
Some checks failed
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-07-26 09:05:36 -07:00
Ross Scroggs
a64f4d4a46 Update GamUpdates.md
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-07-25 13:33:50 -07:00
Ross Scroggs
c396a3b901 Update Shared Drive restriction settings 2025-07-25 12:58:57 -07:00
Ross Scroggs
78453a15af Update Shared Drive restriction settings 2025-07-25 12:58:34 -07:00
Ross Scroggs
a0282ba775 Updated gam print shareddriveorganizers; code iter() cleanup
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-07-24 16:20:58 -07:00
11 changed files with 145 additions and 286 deletions

View File

@@ -4860,8 +4860,8 @@ gam <UserTypeEntity> sendemail from <EmailAddress>
allowcontentmanagerstosharefolders|
copyrequireswriterpermission|
domainusersonly|
downloadrestrictedforreaders|
downloadrestrictedforwriters|
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
@@ -4878,7 +4878,7 @@ In these commands, the Google administrator named in oauth2.txt is used.
gam show shareddrivethemes
gam create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>]
@@ -4932,7 +4932,7 @@ In these commands, you specify an administrator and then indicate that you want
gam <UserTypeEntity> create shareddrive <Name> adminaccess
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>]
@@ -4966,7 +4966,7 @@ In these commands, you specify a user, administrator access is not used.
gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>]
@@ -8475,8 +8475,8 @@ gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
allowcontentmanagerstosharefolders|
copyrequireswriterpermission|
domainusersonly|
downloadrestrictedforreaders|
downloadrestrictedforwriters|
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
@@ -8491,13 +8491,13 @@ sharingfoldersrequiresorganizerpermission true
gam <UserTypeEntity> show shareddrivethemes
gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [name <Name>]
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>]
gam <UserTypeEntity> delete shareddrive <SharedDriveEntity>
[allowitemdeletion]

View File

@@ -1,3 +1,18 @@
7.16.00
Removed `drive_v3_native_names` from `gam.cfg`; GAM now only uses Drive API v3 fields names on output.
If you had `drive_v3_native_names = False` in `gam.cfg` or are updating from Legacy GAM:
* See: https://github.com/GAM-team/GAM/wiki/Drive-REST-API-v3
7.15.01
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
and `downloadrestrictedforwriters` were supported (they are still supported).
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
7.15.00
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.15.00'
__version__ = '7.16.00'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -7862,7 +7862,6 @@ class CSVPrintFile():
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '')
self.SetTimestampColumn(GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN])
self.SetFormatJSON(False)
self.SetMapDrive3Titles(False)
self.SetNodataFields(False, None, None, None, False)
self.SetFixPaths(False)
self.SetShowPermissionsLast(False)
@@ -7932,13 +7931,6 @@ class CSVPrintFile():
self.sortTitlesList = self.titlesList[:]
self.sortTitlesSet = set(self.sortTitlesList)
def SetMapDrive3Titles(self, mapDrive3Titles):
self.mapDrive3Titles = mapDrive3Titles
def MapDrive3TitlesToDrive2(self):
_mapDrive3TitlesToDrive2(self.titlesList, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
self.titlesSet = set(self.titlesList)
def AddJSONTitle(self, title):
self.JSONtitlesSet.add(title)
self.JSONtitlesList.append(title)
@@ -8974,7 +8966,6 @@ class CSVPrintFile():
self.formatJSON, self.JSONtitlesList,
self.columnDelimiter, self.noEscapeChar, self.quoteChar,
self.sortHeaders, self.timestampColumn,
self.mapDrive3Titles,
self.fixPaths,
self.mapNodataFields,
self.nodataFields,
@@ -9009,8 +9000,6 @@ class CSVPrintFile():
self.MovePermsToEnd()
if not self.rows and self.nodataFields is not None:
self.FixNodataTitles()
if self.mapDrive3Titles:
self. MapDrive3TitlesToDrive2()
else:
self.titlesList = self.headerForce
if self.timestampColumn:
@@ -9646,11 +9635,10 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
csvPF.SetQuoteChar(dataItem[7])
csvPF.SetSortHeaders(dataItem[8])
csvPF.SetTimestampColumn(dataItem[9])
csvPF.SetMapDrive3Titles(dataItem[10])
csvPF.SetFixPaths(dataItem[11])
csvPF.SetNodataFields(dataItem[12], dataItem[13], dataItem[14], dataItem[15], dataItem[16])
csvPF.SetShowPermissionsLast(dataItem[17])
csvPF.SetZeroBlankMimeTypeCounts(dataItem[18])
csvPF.SetFixPaths(dataItem[10])
csvPF.SetNodataFields(dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15])
csvPF.SetShowPermissionsLast(dataItem[16])
csvPF.SetZeroBlankMimeTypeCounts(dataItem[17])
elif dataType == GM.REDIRECT_QUEUE_DATA:
csvPF.rows.extend(dataItem)
elif dataType == GM.REDIRECT_QUEUE_ARGS:
@@ -54605,11 +54593,6 @@ DRIVEFILE_ORDERBY_CHOICE_MAP = {
'viewedbymetime': 'viewedByMeTime',
}
def _mapDrive3TitlesToDrive2(titles, drive3TitlesMap):
for i, title in enumerate(titles):
if title in drive3TitlesMap:
titles[i] = drive3TitlesMap[title]
def _mapDriveUser(field):
if 'me' in field:
field['isAuthenticatedUser'] = field.pop('me')
@@ -54617,32 +54600,25 @@ def _mapDriveUser(field):
field['picture'] = {'url': field.pop('photoLink')}
def _mapDrivePermissionNames(permission):
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
if 'displayName' in permission:
permission['name'] = permission.pop('displayName')
if 'expirationTime' in permission:
permission['expirationDate'] = formatLocalTime(permission.pop('expirationTime'))
if 'allowFileDiscovery' in permission:
permission['withLink'] = not permission.pop('allowFileDiscovery')
emailAddress = permission.get('emailAddress')
if emailAddress:
_, permission['domain'] = splitEmailAddress(emailAddress)
def _mapDriveParents(f_file, parentsSubFields):
def _mapDriveInfo(f_file, parentsSubFields, showParentsIdsAsList):
if 'parents' in f_file:
parents = f_file.pop('parents')
if len(parents) == 1 and parents[0] == ORPHANS:
return
f_file['parents'] = []
for parentId in parents:
parent = {}
if parentsSubFields['id']:
parent['id'] = parentId
if parentsSubFields['isRoot']:
parent['isRoot'] = parentId == parentsSubFields['rootFolderId']
f_file['parents'].append(parent)
if showParentsIdsAsList:
f_file['parentsIds'] = parents
elif len(parents) != 1 or parents[0] != ORPHANS:
f_file['parents'] = []
for parentId in parents:
parent = {}
if parentsSubFields['id']:
parent['id'] = parentId
if parentsSubFields['isRoot']:
parent['isRoot'] = parentId == parentsSubFields['rootFolderId']
f_file['parents'].append(parent)
def _mapDriveProperties(f_file):
appProperties = f_file.pop('appProperties', [])
properties = f_file.pop('properties', [])
if appProperties:
@@ -54654,51 +54630,10 @@ def _mapDriveProperties(f_file):
for key, value in sorted(properties.items()):
f_file['properties'].append({'key': key, 'value': value, 'visibility': 'PUBLIC'})
def _mapDriveFieldNames(f_file, user, parentsSubFields, mapToLabels):
if mapToLabels:
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_LABELS_MAP.items():
if attrib in f_file:
f_file.setdefault('labels', {})
f_file['labels'][v2attrib] = f_file.pop(attrib)
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP.items():
if attrib in f_file:
f_file[v2attrib] = f_file.pop(attrib)
capabilities = f_file.get('capabilities')
if capabilities:
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP.items():
if attrib in capabilities:
f_file[v2attrib] = capabilities[attrib]
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP.items():
if attrib in capabilities:
capabilities[v2attrib] = capabilities.pop(attrib)
if 'spaces' in f_file:
f_file['appDataContents'] = 'appDataFolder' in f_file['spaces']
if 'lastModifyingUser' in f_file:
if 'displayName' in f_file['lastModifyingUser']:
f_file['lastModifyingUserName'] = f_file['lastModifyingUser']['displayName']
_mapDriveUser(f_file['lastModifyingUser'])
if 'owners' in f_file:
for owner in f_file['owners']:
_mapDriveUser(owner)
if 'displayName' in owner:
f_file.setdefault('ownerNames', [])
f_file['ownerNames'].append(owner['displayName'])
_mapDriveUser(f_file.get('sharingUser', {}))
_mapDriveParents(f_file, parentsSubFields)
_mapDriveProperties(f_file)
for permission in f_file.get('permissions', []):
if (permission.get('type') == 'user') and (permission.get('emailAddress', '').lower() == user) and ('role' in permission):
f_file['userPermission'] = {'id': 'me', 'role': permission['role'], 'type': permission['type']}
_mapDrivePermissionNames(permission)
def _mapDriveRevisionNames(revision):
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP.items():
if attrib in revision:
revision[v2attrib] = revision.pop(attrib)
if 'lastModifyingUser' in revision:
if 'displayName' in revision['lastModifyingUser']:
revision['lastModifyingUserName'] = revision['lastModifyingUser']['displayName']
_mapDriveUser(revision['lastModifyingUser'])
emailAddress = permission.get('emailAddress')
if emailAddress:
_, permission['domain'] = splitEmailAddress(emailAddress)
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
@@ -54949,11 +54884,7 @@ FILEINFO_FIELDS_TITLES = ['name', 'mimeType']
FILEPATH_FIELDS_TITLES = ['name', 'id', 'mimeType', 'ownedByMe', 'parents', 'sharedWithMeTime', 'driveId']
FILEPATH_FIELDS = ','.join(FILEPATH_FIELDS_TITLES)
def _getDriveTimeObjects():
timeObjects = ['createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime']
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return set(timeObjects)
DRIVE_TIME_OBJECTS = {'createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime'}
def _getDriveFieldSubField(field, fieldsList, parentsSubFields):
field, subField = field.split('.', 1)
@@ -55150,7 +55081,6 @@ def showFileInfo(users):
showNoParents = True
includeLabels = ','.join(DFF.includeLabels)
pathFields = FILEPATH_FIELDS
timeObjects = _getDriveTimeObjects()
i, count, users = getEntityArgument(users)
for user in users:
i += 1
@@ -55244,22 +55174,14 @@ def showFileInfo(users):
if fullpath:
# Save simple parents list as mappings turn it into a list of dicts
fpparents = result['parents'][:]
if showParentsIdsAsList and 'parents' in result:
result['parentsIds'] = result.pop('parents')
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveFieldNames(result, user, DFF.parentsSubFields, True)
else:
_mapDriveParents(result, DFF.parentsSubFields)
_mapDriveProperties(result)
for permission in result.get('permissions', []):
_mapDrivePermissionNames(permission)
_mapDriveInfo(result, DFF.parentsSubFields, showParentsIdsAsList)
if not FJQC.formatJSON:
showJSON(None, result, skipObjects=skipObjects, timeObjects=timeObjects, simpleLists=simpleLists,
showJSON(None, result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS, simpleLists=simpleLists,
dictObjectsKey={'owners': 'displayName', 'fields': 'id', 'labels': 'id', 'user': 'emailAddress', 'parents': 'id',
'permissions': ['name', 'displayName'][GC.Values[GC.DRIVE_V3_NATIVE_NAMES]]})
'permissions': 'displayName'})
Ind.Decrement()
else:
printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=timeObjects), ensure_ascii=False, sort_keys=True))
printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
if fullpath:
# Restore simple parents list
fileTree[fileId]['info']['parents'] = fpparents[:]
@@ -55651,18 +55573,12 @@ FILEREVISIONS_FIELDS_CHOICE_MAP = {
'size': 'size',
}
def _getFileRevisionsTimeObjects():
timeObjects = ['modifiedTime']
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return set(timeObjects)
FILEREVISIONS_TIME_OBJECTS = {'modifiedTime'}
def _showRevision(revision, timeObjects, i=0, count=0):
def _showRevision(revision, i=0, count=0):
printEntity([Ent.DRIVE_FILE_REVISION, revision['id']], i, count)
Ind.Increment()
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveRevisionNames(revision)
showJSON(None, revision, ['id'], timeObjects)
showJSON(None, revision, ['id'], timeObjects=FILEREVISIONS_TIME_OBJECTS)
Ind.Decrement()
DRIVE_REVISIONS_INDEXED_TITLES = ['revisions']
@@ -55686,7 +55602,6 @@ def printShowFileRevisions(users):
revisionsEntity = None
oneItemPerRow = previewDelete = showTitles = stripCRsFromName = False
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -55704,7 +55619,7 @@ def printShowFileRevisions(users):
elif myarg == 'showtitles':
showTitles = True
if csvPF:
csvPF.AddTitles(fileNameTitle)
csvPF.AddTitles('name')
elif myarg == 'stripcrsfromname':
stripCRsFromName = True
elif getFieldsList(myarg, FILEREVISIONS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'):
@@ -55715,7 +55630,6 @@ def printShowFileRevisions(users):
fields = getItemFieldsFromFieldsList('revisions', fieldsList)
else:
fields = '*'
timeObjects = _getFileRevisionsTimeObjects()
i, count, users = getEntityArgument(users)
for user in users:
i += 1
@@ -55755,29 +55669,24 @@ def printShowFileRevisions(users):
k = 0
for revision in results:
k += 1
_showRevision(revision, timeObjects, k, kcount)
_showRevision(revision, k, kcount)
Ind.Decrement()
elif results:
if oneItemPerRow:
for revision in results:
row = {'Owner': user, 'id': fileId}
if showTitles:
row[fileNameTitle] = fileName
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveRevisionNames(revision)
csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=timeObjects))
row['name'] = fileName
csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=FILEREVISIONS_TIME_OBJECTS))
else:
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
for revision in results:
_mapDriveRevisionNames(revision)
if showTitles:
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, fileNameTitle: fileName}, timeObjects=timeObjects))
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, 'name': fileName}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
else:
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=timeObjects))
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
Ind.Decrement()
if csvPF:
if oneItemPerRow:
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle, 'revision.id'])
csvPF.SetSortTitles(['Owner', 'id', 'name', 'revision.id'])
else:
csvPF.SetSortTitles(['Owner', 'id', 'revisions'])
csvPF.SetIndexedTitles(DRIVE_REVISIONS_INDEXED_TITLES)
@@ -56587,10 +56496,10 @@ def printFileList(users):
def _printFileInfoRow(baserow, fileInfo):
row = baserow.copy()
if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter))
else:
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row)
@@ -56641,15 +56550,7 @@ def printFileList(users):
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
else:
addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly)
if showParentsIdsAsList and 'parents' in fileInfo:
fileInfo['parentsIds'] = fileInfo.pop('parents')
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveFieldNames(fileInfo, user, DFF.parentsSubFields, False)
else:
_mapDriveParents(fileInfo, DFF.parentsSubFields)
_mapDriveProperties(fileInfo)
for permission in fileInfo.get('permissions', []):
_mapDrivePermissionNames(permission)
_mapDriveInfo(fileInfo, DFF.parentsSubFields, showParentsIdsAsList)
if showParentsIdsAsList and 'parentsIds' in fileInfo:
fileInfo['parents'] = len(fileInfo['parentsIds'])
if addCSVData:
@@ -56657,24 +56558,24 @@ def printFileList(users):
if not countsOnly:
if not oneItemPerRow or 'permissions' not in fileInfo:
if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter))
else:
if 'id' in fileInfo:
row['id'] = fileInfo['id']
if fileNameTitle in fileInfo:
row[fileNameTitle] = fileInfo[fileNameTitle]
if 'name' in fileInfo:
row['name'] = fileInfo['name']
if 'owners' in fileInfo:
flattenJSON({'owners': fileInfo['owners']}, flattened=row, skipObjects=skipObjects)
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row)
else:
baserow = row.copy()
if 'id' in fileInfo:
baserow['id'] = fileInfo['id']
if fileNameTitle in fileInfo:
baserow[fileNameTitle] = fileInfo[fileNameTitle]
if 'name' in fileInfo:
baserow['name'] = fileInfo['name']
if 'owners' in fileInfo:
flattenJSON({'owners': fileInfo['owners']}, flattened=baserow, skipObjects=skipObjects)
for permission in fileInfo.pop('permissions'):
@@ -56688,7 +56589,7 @@ def printFileList(users):
_printFileInfoRow(baserow, fileInfo)
else:
if not countsRowFilter:
csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter), mimeTypeInfo, sizeField)
else:
mimeTypeInfo.setdefault(fileInfo['mimeType'], {'count': 0, 'size': 0})
@@ -56955,12 +56856,6 @@ def printFileList(users):
csvPF.AddTitles('paths')
csvPF.SetFixPaths(True)
includeLabels = ','.join(DFF.includeLabels)
timeObjects = _getDriveTimeObjects()
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
fileNameTitle = 'title'
csvPF.SetMapDrive3Titles(True)
else:
fileNameTitle = 'name'
csvPF.RemoveTitles(['capabilities'])
if DLP.queryTimes and selectSubQuery:
for queryTimeName, queryTimeValue in DLP.queryTimes.items():
@@ -56980,9 +56875,9 @@ def printFileList(users):
if not FJQC.formatJSON:
nodataFields = ['Owner']+list(set(DFF.fieldsList)-skipObjects)
else:
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress']
nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
else:
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress']
nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
if not FJQC.formatJSON:
nodataFields.append('permissions')
if filepath:
@@ -57162,7 +57057,7 @@ def printFileList(users):
if not csvPF.rows:
setSysExitRC(NO_ENTITIES_FOUND_RC)
if not FJQC.formatJSON:
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle])
csvPF.SetSortTitles(['Owner', 'id', 'name'])
else:
if 'JSON' in csvPF.JSONtitlesList:
csvPF.MoveJSONTitlesToEnd(['JSON'])
@@ -57430,8 +57325,7 @@ def printShowFileComments(users):
# [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
# [followshortcuts [<Boolean>]]
def printShowFilePaths(users):
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
csvPF = CSVPrintFile(['Owner', 'id', fileNameTitle, 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
csvPF = CSVPrintFile(['Owner', 'id', 'name', 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
fileIdEntity = getDriveFileEntity()
fullpath = folderPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False
pathDelimiter = '/'
@@ -57532,11 +57426,11 @@ def printShowFilePaths(users):
if oneItemPerRow:
if paths:
for path in paths:
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name'], 'path': path})
csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name'], 'path': path})
else:
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name']})
csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name']})
else:
csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, fileNameTitle: result['name']}))
csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, 'name': result['name']}))
except GAPI.fileNotFound:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], Msg.DOES_NOT_EXIST, j, jcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
@@ -57549,8 +57443,7 @@ def printShowFilePaths(users):
# gam <UserTypeEntity> print fileparenttree <DriveFileEntity> [todrive <ToDriveAttribute>*]
# [stripcrsfromname]
def printFileParentTree(users):
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', fileNameTitle, 'parentId', 'depth', 'isRoot'], 'sortall')
csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', 'name', 'parentId', 'depth', 'isRoot'], 'sortall')
fileIdEntity = getDriveFileEntity()
stripCRsFromName = False
while Cmd.ArgumentsRemaining():
@@ -57610,7 +57503,7 @@ def printFileParentTree(users):
kcount = len(fileList)
isBase = True
for result in fileList:
csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], fileNameTitle: result['name'],
csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], 'name': result['name'],
'parentId': result['parents'][0], 'depth': kcount, 'isRoot': result['isRoot']})
isBase = False
kcount -= 1
@@ -58409,7 +58302,7 @@ def printShowFileTree(users):
userInfo['index'] += 1
row = userInfo.copy()
row['depth'] = depth
row[fileNameTitle] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name']
row['name'] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name']
for field in FILETREE_FIELDS_PRINT_ORDER:
if showFields[field]:
if field == 'parents':
@@ -58417,7 +58310,7 @@ def printShowFileTree(users):
elif field == 'owners':
row[field] = delimiter.join([owner['emailAddress'] for owner in fileEntry.get(field, [])])
elif field == 'size':
row[fileSize] = fileEntry.get(sizeField, 0)
row['size'] = fileEntry.get(sizeField, 0)
else:
row[field] = fileEntry.get(field, '')
csvPF.WriteRow(row)
@@ -58518,14 +58411,6 @@ def printShowFileTree(users):
unknownArgumentExit()
fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)',
'shared', sizeField, 'explicitlyTrashed', 'trashed', 'webViewLink']
if csvPF:
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
fileNameTitle = 'title'
fileSize = 'fileSize'
csvPF.SetMapDrive3Titles(True)
else:
fileNameTitle = 'name'
fileSize = 'size'
buildTree = (not fileIdEntity
or (not fileIdEntity['dict']
and not fileIdEntity['query']
@@ -58585,7 +58470,7 @@ def printShowFileTree(users):
if jcount == 0:
continue
if csvPF:
userInfo = {'User': user, 'index': 0, 'depth': 0, fileNameTitle: ''}
userInfo = {'User': user, 'index': 0, 'depth': 0, 'name': ''}
j = 0
Ind.Increment()
for fileId in fileIdEntity['list']:
@@ -58745,8 +58630,7 @@ def createDriveFile(users):
media_body = getMediaBody(parameters)
body['mimeType'] = parameters[DFA_LOCALMIMETYPE]
if csvPF:
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
csvPF.SetTitles(['User', fileNameTitle, 'id'])
csvPF.SetTitles(['User', 'name', 'id'])
if showDetails:
csvPF.AddTitles(['parentId', 'mimeType'])
if addCSVData:
@@ -58806,7 +58690,7 @@ def createDriveFile(users):
else:
entityActionPerformed(kvList, i, count)
else:
row = {'User': user, fileNameTitle: result['name'], 'id': result['id']}
row = {'User': user, 'name': result['name'], 'id': result['id']}
if showDetails:
row.update({'parentId': parentId, 'mimeType': result['mimeType']})
if addCSVData:
@@ -60309,7 +60193,7 @@ def _checkForExistingShortcut(drive, fileId, fileName, parentId):
supportsAllDrives=True, includeItemsFromAllDrives=True,
q=f"shortcutDetails.targetId = '{fileId}' and trashed = False", fields='files(id,name,parents)')['files']
for shortcut in existingShortcuts:
if parentId in shortcut['parents'] and fileName == shortcut['name']:
if parentId in shortcut.get('parents', []) and fileName == shortcut['name']:
return shortcut['id']
except (GAPI.invalidQuery, GAPI.invalid, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
pass
@@ -60362,8 +60246,8 @@ copyReturnItemMap = {
# [enforceexpansiveaccess [<Boolean>]]
def copyDriveFile(users):
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
row = {'User': user, fileNameTitle: oldName, 'id': oldId,
newFileNameTitle: newName, 'newId': newId, 'mimeType': mimeType}
row = {'User': user, 'name': oldName, 'id': oldId,
'newName': newName, 'newId': newId, 'mimeType': mimeType}
if addCSVData:
row.update(addCSVData)
csvPF.WriteRow(row)
@@ -60753,9 +60637,7 @@ def copyDriveFile(users):
else:
unknownArgumentExit()
if csvPF:
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
newFileNameTitle = f'new{fileNameTitle.capitalize()}'
csvPF.SetTitles(['User', fileNameTitle, 'id', newFileNameTitle, 'newId', 'mimeType'])
csvPF.SetTitles(['User', 'name', 'id', 'newName', 'newId', 'mimeType'])
if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys()))
i, count, users = getEntityArgument(users)
@@ -64155,11 +64037,8 @@ def _getDriveFileACLPrintKeysTimeObjects():
printKeys = ['id', 'type', 'emailAddress', 'domain', 'role', 'permissionDetails',
'expirationTime', 'photoLink', 'allowFileDiscovery', 'deleted',
'pendingOwner', 'view']
timeObjects = ['expirationTime']
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDrive3TitlesToDrive2(printKeys, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return (printKeys, set(timeObjects))
timeObjects = {'expirationTime'}
return (printKeys, timeObjects)
# DriveFileACL commands utilities
def _showDriveFilePermissionJSON(user, fileId, fileName, createdTime, permission, timeObjects):
@@ -64251,7 +64130,6 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
showDetails = True
csvPF = None
FJQC = FormatJSONQuoteChar(csvPF)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
fileIdEntity = getDriveFileEntity()
body = {}
body['type'] = permType = getChoice(DRIVEFILE_ACL_PERMISSION_TYPES)
@@ -64327,7 +64205,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
if csvPF:
if showTitles:
csvPF.AddTitles(fileNameTitle)
csvPF.AddTitles('name')
csvPF.SetSortAllTitles()
if FJQC.formatJSON:
csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
@@ -64366,7 +64244,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow[fileNameTitle] = fileName
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
@@ -64422,7 +64300,6 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
showDetails = True
csvPF = None
FJQC = FormatJSONQuoteChar(csvPF)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
body = {}
while Cmd.ArgumentsRemaining():
myarg = getArgument()
@@ -64457,7 +64334,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
if csvPF and showTitles:
csvPF.AddTitles(fileNameTitle)
csvPF.AddTitles('name')
csvPF.SetSortAllTitles()
if FJQC.formatJSON:
csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
@@ -64500,7 +64377,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow[fileNameTitle] = fileName
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
@@ -65065,7 +64942,6 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
fieldsList = []
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
PM = PermissionMatch()
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -65084,7 +64960,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
addTitle = getString(Cmd.OB_STRING)
showTitles = False
if csvPF:
csvPF.AddTitles(fileNameTitle)
csvPF.AddTitles('name')
csvPF.SetSortAllTitles()
elif getDriveFilePermissionsFields(myarg, fieldsList):
pass
@@ -65169,7 +65045,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
else:
baserow = {'Owner': user, 'id': fileId}
if showTitles or addTitle:
baserow[fileNameTitle] = fileName
baserow['name'] = fileName
if oneItemPerRow:
for permission in permissions:
_mapDrivePermissionNames(permission)
@@ -65736,7 +65612,6 @@ def doPrintShowOwnership():
customerId = GC.Values[GC.CUSTOMER_ID]
if customerId == GC.MY_CUSTOMER:
customerId = None
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
csvPF = CSVPrintFile('Owner') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
addCSVData = {}
@@ -65781,7 +65656,7 @@ def doPrintShowOwnership():
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
if csvPF and not FJQC.formatJSON:
csvPF.AddTitles(['id', fileNameTitle, 'type', 'ownerIsSharedDrive', 'driveId', 'event'])
csvPF.AddTitles(['id', 'name', 'type', 'ownerIsSharedDrive', 'driveId', 'event'])
if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys()))
csvPF.SetSortAllTitles()
@@ -65814,7 +65689,7 @@ def doPrintShowOwnership():
elif event['name'] != 'change_owner' and item['name'] == 'owner':
fileInfo['Owner'] = item['value']
elif item['name'] == 'doc_title':
fileInfo[fileNameTitle] = item['value']
fileInfo['name'] = item['value']
elif item['name'] == 'doc_type':
fileInfo['type'] = item['value']
elif item['name'] == 'owner_is_shared_drive':
@@ -65827,7 +65702,7 @@ def doPrintShowOwnership():
if not csvPF:
if not FJQC.formatJSON:
printEntityKVList([Ent.OWNER, fileInfo['Owner']],
['id', fileInfo['id'], fileNameTitle, fileInfo.get(fileNameTitle, ''),
['id', fileInfo['id'], 'name', fileInfo.get('name', ''),
'type', fileInfo.get('type', ''),
'ownerIsSharedDrive', fileInfo.get('ownerIsSharedDrive', False),
'driveId', fileInfo.get('driveId', ''),
@@ -65885,6 +65760,10 @@ SHAREDDRIVE_RESTRICTIONS_MAP = {
'sharingfoldersrequiresorganizerpermission': 'sharingFoldersRequiresOrganizerPermission',
'teammembersonly': 'driveMembersOnly',
}
SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP = {
'restrictedforreaders': 'downloadrestrictedforreaders',
'restrictedforwriters': 'downloadrestrictedforwriters',
}
def _getSharedDriveRestrictions(myarg, body):
def _setRestriction(restriction):
@@ -65899,7 +65778,12 @@ def _getSharedDriveRestrictions(myarg, body):
if myarg.startswith('restrictions.'):
_, subField = myarg.split('.', 1)
if subField in SHAREDDRIVE_RESTRICTIONS_MAP:
if subField.startswith('downloadrestrictions.'):
_, subField = subField.split('.', 1)
if subField in SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP:
_setRestriction(SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP[subField])
return True
elif subField in SHAREDDRIVE_RESTRICTIONS_MAP:
_setRestriction(subField)
return True
invalidChoiceExit(subField, SHAREDDRIVE_RESTRICTIONS_MAP, True)

View File

@@ -750,56 +750,6 @@ _USER_SVCACCT_ONLY_SCOPES = [
'scope': 'https://www.googleapis.com/auth/apps.groups.migration'},
]
DRIVE3_TO_DRIVE2_ABOUT_FIELDS_MAP = {
'displayName': 'name',
'limit': 'quotaBytesTotal',
'usage': 'quotaBytesUsedAggregate',
'usageInDrive': 'quotaBytesUsed',
'usageInDriveTrash': 'quotaBytesUsedInTrash',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP = {
'canComment': 'canComment',
'canReadRevisions': 'canReadRevisions',
'canCopy': 'copyable',
'canEdit': 'editable',
'canShare': 'shareable',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP = {
'canChangeViewersCanCopyContent': 'canChangeRestrictedDownload',
}
DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP = {
'allowFileDiscovery': 'withLink',
'createdTime': 'createdDate',
'expirationTime': 'expirationDate',
'modifiedByMe': 'modified',
'modifiedByMeTime': 'modifiedByMeDate',
'modifiedTime': 'modifiedDate',
'name': 'title',
'restrictionTime': 'restrictionDate',
'sharedWithMeTime': 'sharedWithMeDate',
'size': 'fileSize',
'trashedTime': 'trashedDate',
'viewedByMe': 'viewed',
'viewedByMeTime': 'lastViewedByMeDate',
'webViewLink': 'alternateLink',
}
DRIVE3_TO_DRIVE2_LABELS_MAP = {
'modifiedByMe': 'modified',
'starred': 'starred',
'trashed': 'trashed',
'viewedByMe': 'viewed',
}
DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP = {
'modifiedTime': 'modifiedDate',
'keepForever': 'pinned',
'size': 'fileSize',
}
def getAPIName(api):
return _INFO[api]['name']

View File

@@ -155,8 +155,6 @@ DRIVE_DIR = 'drive_dir'
DRIVE_MAX_RESULTS = 'drive_max_results'
# Use Drive V3 beta
DRIVE_V3_BETA = 'drive_v3_beta'
# Use Drive V3 ntive names
DRIVE_V3_NATIVE_NAMES = 'drive_v3_native_names'
# When processing email messages in batches, how many should be processed in each batch
EMAIL_BATCH_SIZE = 'email_batch_size'
# Enable Delegated Admin Service Account
@@ -382,7 +380,6 @@ Defaults = {
ENFORCE_EXPANSIVE_ACCESS: TRUE,
DRIVE_MAX_RESULTS: '1000',
DRIVE_V3_BETA: FALSE,
DRIVE_V3_NATIVE_NAMES: TRUE,
EMAIL_BATCH_SIZE: '50',
ENABLE_DASA: FALSE,
ENABLE_GCLOUD_REAUTH: FALSE,
@@ -551,7 +548,6 @@ VAR_INFO = {
ENFORCE_EXPANSIVE_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN},
DRIVE_V3_NATIVE_NAMES: {VAR_TYPE: TYPE_BOOLEAN},
EMAIL_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
ENABLE_DASA: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'enabledasa.txt', VAR_SFFT: (FALSE, TRUE)},
ENABLE_GCLOUD_REAUTH: {VAR_TYPE: TYPE_BOOLEAN},

View File

@@ -10,6 +10,21 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.15.01
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
and `downloadrestrictedforwriters` were supported (they are still supported).
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
### 7.15.00
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`
as documented; it was defaulting to `False`.
Cleaned up code for processing Python dictionary structures; this should have no noticable effect.
### 7.14.04
Fixed bug in `gam print|show cigroups cimember <UserItem>` that generated the following error:

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.15.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64
@@ -989,7 +989,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.14.04 - https://github.com/GAM-team/GAM - pythonsource
GAM 7.15.01 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -203,8 +203,8 @@
allowcontentmanagerstosharefolders|
copyrequireswriterpermission|
domainusersonly|
downloadrestrictedforreaders|
downloadrestrictedforwriters|
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
@@ -247,7 +247,7 @@ The user that creates a Shared Drive is given the permission role organizer for
gam [<UserTypeEntity>] create shareddrive <Name>
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
@@ -259,7 +259,7 @@ gam [<UserTypeEntity>] create shareddrive <Name>
* `<Float>` - Y coordinate, typically 0.0
* `<Float>` - width, typically 1.0
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hide <Boolean>` - Set Shared Drive visibility
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
@@ -333,13 +333,13 @@ gam [<UserTypeEntity>] update shareddrive <SharedDriveEntity> [name <Name>]
[adminaccess|asadmin]
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
```
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hidden <Boolean>` - Set Shared Drive visibility
* `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html

View File

@@ -181,8 +181,8 @@
allowcontentmanagerstosharefolders|
copyrequireswriterpermission|
domainusersonly|
downloadrestrictedforreaders|
downloadrestrictedforwriters|
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
@@ -217,7 +217,7 @@ The user that creates a Shared Drive is given the permission role organizer for
gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
@@ -228,7 +228,7 @@ gam <UserTypeEntity> create shareddrive <Name>
* `<Float>` - Y coordinate, typically 0.0
* `<Float>` - width, typically 1.0
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hide <Boolean>` - Set Shared Drive visibility
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
@@ -284,13 +284,13 @@ This command is used to set basic Shared Drive settings.
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [adminaccess|asadmin] [name <Name>]
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
```
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hidden <Boolean>` - Set Shared Drive visibility
This option is only available when the command is run as an administrator.

View File

@@ -4,7 +4,7 @@ k
Print the current version of Gam with details
```
gam version
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.15.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64
@@ -16,7 +16,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.15.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64
@@ -28,7 +28,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.15.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64
@@ -65,7 +65,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7
Version Check:
Current: 5.35.08
Latest: 7.14.04
Latest: 7.15.01
echo $?
1
```
@@ -73,7 +73,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.14.04
7.15.01
```
In Linux/MacOS you can do:
```
@@ -83,7 +83,7 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.14.04 - https://github.com/GAM-team/GAM
GAM 7.15.01 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64

View File

@@ -412,9 +412,8 @@ never_time
has the value "1970-01-01T00:00:00.000Z"
Default: Never
no_browser
If no_browser is True, GAM won't open a browser if todrive is set
when creating CSV files and GAM prints a link and waits for
the verification code when oauth2.txt is being created
If no_browser is True, GAM won't open a browser when it prints a link
and waits for the verification code when oauth2.txt is being created/updated
Signal file: OldGamPath/nobrowser.txt
no_cache
Disable GAM API caching