Compare commits

...

22 Commits

Author SHA1 Message Date
Ross Scroggs
e82baccbac Merge branch 'main' of https://github.com/GAM-team/GAM 2025-05-28 09:02:43 -07:00
Ross Scroggs
c51b06a6c3 Update gam setup chat output 2025-05-28 09:01:22 -07:00
Jay Lee
b7415cd63f forward compat fix for setuptools issue #1778 2025-05-28 14:06:37 +00:00
Jay Lee
f0f5803698 no need to pin pyscard any longer, align requirements 2025-05-28 13:21:06 +00:00
Ross Scroggs
575fdea526 Use setuptools 80.8.0
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-05-27 18:31:39 -07:00
Ross Scroggs
f8ee94bad8 Update Users-Drive-Permissions.md 2025-05-27 17:47:34 -07:00
Ross Scroggs
4b6c8fb518 Update Users-Drive-Permissions.md 2025-05-27 17:08:26 -07:00
Ross Scroggs
4f8c80dcab Added option showitemcountonly to gam [<UserTypeEntity>] print|show shareddrives 2025-05-27 13:21:43 -07:00
Ross Scroggs
12f5c5e670 Added option showitemcountonly to gam [<UserTypeEntity>] print|show shareddrives 2025-05-27 13:21:31 -07:00
Ross Scroggs
a1216b6782 Update Users-Drive-Copy-Move.md
Some checks failed
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
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-05-27 08:00:13 -07:00
Ross Scroggs
05f4795bc3 Update Users-Drive-Copy-Move.md 2025-05-27 07:58:12 -07:00
Ross Scroggs
e1ff1ba378 Update Users-Drive-Copy-Move.md 2025-05-27 07:56:47 -07:00
Ross Scroggs
5b2804643e Fixed bug in gam print|show oushareddrives that caused a trap.
Some checks failed
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
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Improved getting Shared Drive names from IDs when accessing Shared Drives in external workspaces.
2025-05-26 12:41:34 -07:00
Ross Scroggs
3925166987 Fixed bug in gam print|show oushareddrives that caused a trap.
Improved getting Shared Drive names from IDs when accessing Shared Drives in external workspaces.
2025-05-26 12:41:09 -07:00
Ross Scroggs
5dece6c719 Update Groups.md
Some checks failed
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
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-05-26 09:15:13 -07:00
Ross Scroggs
b48d316bd9 Update gam.cfg.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-05-25 17:45:11 -07:00
Ross Scroggs
1f2b33b805 Handle additional API errors
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
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
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-05-23 20:14:47 -07:00
Ross Scroggs
a6773901c9 Handle additional API errors 2025-05-23 20:14:36 -07:00
Ross Scroggs
840784fa98 Update Authorization.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
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-05-23 14:43:55 -07:00
Ross Scroggs
aecb17b9fe Handle API additional errors in update events, part II 2025-05-23 12:57:50 -07:00
Ross Scroggs
2d90c75f03 Handle API additional errors in update events, part II 2025-05-23 12:57:38 -07:00
Ross Scroggs
cd8691b438 Handle API additional errors in update events
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-05-23 09:26:39 -07:00
21 changed files with 310 additions and 101 deletions

View File

@@ -449,7 +449,7 @@ jobs:
"$PYTHON" get-pip.py "$PYTHON" get-pip.py
"$PYTHON" -m pip install --upgrade pip "$PYTHON" -m pip install --upgrade pip
"$PYTHON" -m pip install --upgrade wheel "$PYTHON" -m pip install --upgrade wheel
"$PYTHON" -m pip install --upgrade setuptools "$PYTHON" -m pip install setuptools
"$PYTHON" -m pip install --upgrade importlib-metadata "$PYTHON" -m pip install --upgrade importlib-metadata
"$PYTHON" -m pip install --upgrade setuptools-scm "$PYTHON" -m pip install --upgrade setuptools-scm
"$PYTHON" -m pip list "$PYTHON" -m pip list

View File

@@ -21,8 +21,8 @@ dependencies = [
"lxml>=5.4.0", "lxml>=5.4.0",
"passlib>=1.7.4", "passlib>=1.7.4",
"pathvalidate>=3.2.3", "pathvalidate>=3.2.3",
"pyscard==2.2.1",
"python-dateutil", "python-dateutil",
"yubikey-manager>=5.6.1",
] ]
description = "CLI tool to manage Google Workspace" description = "CLI tool to manage Google Workspace"
readme = "README.md" readme = "README.md"

View File

@@ -1,3 +1,42 @@
7.07.14
Update `gam setup chat` output to include the following that shows the actual Cloud Pub/Sub Topic Name.
```
You'll use projects/<ProjectID>/topics/no-topic in Connection settings Cloud Pub/Sub Topic Name
```
7.07.13
Added option `showitemcountonly` to `gam [<UserTypeEntity>] print|show shareddrives` that causes GAM to display the
number of Shared Drives on stdout; no CSV file is written.
7.07.12
Fixed bug in `gam print|show oushareddrives` that caused a trap.
Improved getting Shared Drive names from IDs when accessing Shared Drives in external workspaces.
7.07.11
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`
to handle the following error:
```
ERROR: 400: badRequest - Bad Request
```
Updated `gam <UserTypeEntity> move drivefile` to handle the following error:
```
ERROR: 400: shareOutNotPermitted
```
7.07.10
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`
to handle the following error:
```
ERROR: 400: eventTypeRestriction - Attendees cannot be added to 'fromGmail' event with this visibility setting.
```
7.07.09 7.07.09
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>` Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`

View File

@@ -38,6 +38,10 @@ hiddenimports = [
'gam.gamlib.yubikey', 'gam.gamlib.yubikey',
] ]
excludes = [
'pkg_resources',
]
runtime_hooks = [] runtime_hooks = []
a = Analysis( a = Analysis(
['gam/__main__.py'], ['gam/__main__.py'],
@@ -48,7 +52,7 @@ a = Analysis(
hookspath=[], hookspath=[],
hooksconfig={}, hooksconfig={},
runtime_hooks=runtime_hooks, runtime_hooks=runtime_hooks,
excludes=[], excludes=excludes,
win_no_prefer_redirects=False, win_no_prefer_redirects=False,
win_private_assemblies=False, win_private_assemblies=False,
cipher=None, cipher=None,

View File

@@ -3,7 +3,7 @@
# #
# GAM7 # GAM7
# #
# Copyright 2024, All Rights Reserved. # Copyright 2025, All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.07.09' __version__ = '7.07.14'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -25949,7 +25949,7 @@ def _printChatItem(user, citem, parent, entityType, csvPF, FJQC, addCSVData=None
def doSetupChat(): def doSetupChat():
checkForExtraneousArguments() checkForExtraneousArguments()
_, chat , _ = buildChatServiceObject() _, chat , _ = buildChatServiceObject()
writeStdout(Msg.TO_SET_UP_GOOGLE_CHAT.format(setupChatURL(chat))) writeStdout(Msg.TO_SET_UP_GOOGLE_CHAT.format(setupChatURL(chat), GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['project_id']))
def getSpaceName(myarg): def getSpaceName(myarg):
if myarg == 'space': if myarg == 'space':
@@ -39299,7 +39299,7 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN, GAPI.BACKEND_ERROR, throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN, GAPI.BACKEND_ERROR,
GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT, GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE, GAPI.REQUIRED_ACCESS_LEVEL, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE,
GAPI.MALFORMED_WORKING_LOCATION_EVENT], GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.EVENT_TYPE_RESTRICTION, GAPI.BAD_REQUEST],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.BACKEND_ERROR], retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.BACKEND_ERROR],
calendarId=calId, eventId=eventId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True, calendarId=calId, eventId=eventId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True,
body=body, fields=pfields) body=body, fields=pfields)
@@ -39315,7 +39315,8 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
break break
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount) entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
except (GAPI.forbidden, GAPI.backendError, GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit, except (GAPI.forbidden, GAPI.backendError, GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
GAPI.requiredAccessLevel, GAPI.cannotChangeOrganizerOfInstance, GAPI.malformedWorkingLocationEvent) as e: GAPI.requiredAccessLevel, GAPI.cannotChangeOrganizerOfInstance, GAPI.malformedWorkingLocationEvent,
GAPI.eventTypeRestriction, GAPI.badRequest) as e:
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount) entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
except GAPI.notACalendarUser: except GAPI.notACalendarUser:
userCalServiceNotEnabledWarning(calId, i, count) userCalServiceNotEnabledWarning(calId, i, count)
@@ -42020,22 +42021,21 @@ def printShowUserVaultHolds(entityList):
else: else:
printKeyValueList(['Total Holds', totalHolds]) printKeyValueList(['Total Holds', totalHolds])
def _cleanVaultQuery(query, cd): def _cleanVaultQuery(query, cd, drive):
if 'query' in query: if 'query' in query:
if cd is not None: if cd is not None and 'orgUnitInfo' in query['query']:
if 'orgUnitInfo' in query['query']: query['query']['orgUnitInfo']['orgUnitPath'] = convertOrgUnitIDtoPath(cd, query['query']['orgUnitInfo']['orgUnitId'])
query['query']['orgUnitInfo']['orgUnitPath'] = convertOrgUnitIDtoPath(cd, query['query']['orgUnitInfo']['orgUnitId']) if drive is not None and 'sharedDriveInfo' in query['query']:
if 'sharedDriveInfo' in query['query']: query['query']['sharedDriveInfo']['sharedDriveNames'] = []
query['query']['sharedDriveInfo']['sharedDriveNames'] = [] for sharedDriveId in query['query']['sharedDriveInfo']['sharedDriveIds']:
for sharedDriveId in query['query']['sharedDriveInfo']['sharedDriveIds']: query['query']['sharedDriveInfo']['sharedDriveNames'].append(_getSharedDriveNameFromId(drive, sharedDriveId, False))
query['query']['sharedDriveInfo']['sharedDriveNames'].append(_getSharedDriveNameFromId(sharedDriveId))
query['query'].pop('searchMethod', None) query['query'].pop('searchMethod', None)
query['query'].pop('teamDriveInfo', None) query['query'].pop('teamDriveInfo', None)
VAULT_QUERY_TIME_OBJECTS = {'createTime', 'endTime', 'startTime', 'versionDate'} VAULT_QUERY_TIME_OBJECTS = {'createTime', 'endTime', 'startTime', 'versionDate'}
def _showVaultQuery(matterNameId, query, cd, FJQC, k=0, kcount=0): def _showVaultQuery(matterNameId, query, cd, drive, FJQC, k=0, kcount=0):
_cleanVaultQuery(query, cd) _cleanVaultQuery(query, cd, drive)
if FJQC is not None and FJQC.formatJSON: if FJQC is not None and FJQC.formatJSON:
printLine(json.dumps(cleanJSON(query, timeObjects=VAULT_QUERY_TIME_OBJECTS), ensure_ascii=False, sort_keys=False)) printLine(json.dumps(cleanJSON(query, timeObjects=VAULT_QUERY_TIME_OBJECTS), ensure_ascii=False, sort_keys=False))
return return
@@ -42067,7 +42067,7 @@ def doInfoVaultQuery():
queryId, queryName, queryNameId = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId) queryId, queryName, queryNameId = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
else: else:
queryName = getString(Cmd.OB_QUERY_ITEM) queryName = getString(Cmd.OB_QUERY_ITEM)
cd = None cd = drive = None
fieldsList = [] fieldsList = []
FJQC = FormatJSONQuoteChar() FJQC = FormatJSONQuoteChar()
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -42077,8 +42077,8 @@ def doInfoVaultQuery():
queryId, queryName, queryNameId = convertQueryNameToID(v, queryName, matterId, matterNameId) queryId, queryName, queryNameId = convertQueryNameToID(v, queryName, matterId, matterNameId)
elif myarg == 'shownames': elif myarg == 'shownames':
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
_, GM.Globals[GM.ADMIN_DRIVE] = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail()) _, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
if GM.Globals[GM.ADMIN_DRIVE] is None: if drive is None:
return return
elif getFieldsList(myarg, VAULT_QUERY_FIELDS_CHOICE_MAP, fieldsList, initialField=['savedQueryId', 'displayName']): elif getFieldsList(myarg, VAULT_QUERY_FIELDS_CHOICE_MAP, fieldsList, initialField=['savedQueryId', 'displayName']):
pass pass
@@ -42089,7 +42089,7 @@ def doInfoVaultQuery():
query = callGAPI(v.matters().savedQueries(), 'get', query = callGAPI(v.matters().savedQueries(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT], throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
matterId=matterId, savedQueryId=queryId, fields=fields) matterId=matterId, savedQueryId=queryId, fields=fields)
_showVaultQuery(matterNameId, query, cd, FJQC) _showVaultQuery(matterNameId, query, cd, drive, FJQC)
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e: except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e)) entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
@@ -42106,7 +42106,7 @@ def doPrintShowVaultQueries():
csvPF = CSVPrintFile(PRINT_VAULT_QUERIES_TITLES, 'sortall') if Act.csvFormat() else None csvPF = CSVPrintFile(PRINT_VAULT_QUERIES_TITLES, 'sortall') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
matters = [] matters = []
cd = None cd = drive = None
fieldsList = [] fieldsList = []
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -42116,8 +42116,8 @@ def doPrintShowVaultQueries():
matters = shlexSplitList(getString(Cmd.OB_MATTER_ITEM_LIST)) matters = shlexSplitList(getString(Cmd.OB_MATTER_ITEM_LIST))
elif myarg == 'shownames': elif myarg == 'shownames':
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
_, GM.Globals[GM.ADMIN_DRIVE] = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail()) _, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
if GM.Globals[GM.ADMIN_DRIVE] is None: if drive is None:
return return
elif getFieldsList(myarg, VAULT_QUERY_FIELDS_CHOICE_MAP, fieldsList, initialField=['savedQueryId', 'displayName']): elif getFieldsList(myarg, VAULT_QUERY_FIELDS_CHOICE_MAP, fieldsList, initialField=['savedQueryId', 'displayName']):
pass pass
@@ -42179,11 +42179,11 @@ def doPrintShowVaultQueries():
k = 0 k = 0
for query in queries: for query in queries:
k += 1 k += 1
_showVaultQuery(matterNameId, query, cd, FJQC, k, kcount) _showVaultQuery(matterNameId, query, cd, drive, FJQC, k, kcount)
Ind.Decrement() Ind.Decrement()
else: else:
for query in queries: for query in queries:
_cleanVaultQuery(query, cd) _cleanVaultQuery(query, cd, drive)
row = flattenJSON(query, flattened={'matterId': matterId, 'matterName': matterName}, timeObjects=VAULT_QUERY_TIME_OBJECTS) row = flattenJSON(query, flattened={'matterId': matterId, 'matterName': matterName}, timeObjects=VAULT_QUERY_TIME_OBJECTS)
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
@@ -52446,20 +52446,15 @@ def _convertSharedDriveNameToId(drive, user, i, count, fileIdEntity, useDomainAd
','.join([td['id'] for td in tdlist])), i, count) ','.join([td['id'] for td in tdlist])), i, count)
return False return False
def _getSharedDriveNameFromId(sharedDriveId): def _getSharedDriveNameFromId(drive, sharedDriveId, useDomainAdminAccess=False):
sharedDriveName = GM.Globals[GM.MAP_SHAREDDRIVE_ID_TO_NAME].get(sharedDriveId) sharedDriveName = GM.Globals[GM.MAP_SHAREDDRIVE_ID_TO_NAME].get(sharedDriveId)
if not sharedDriveName: if not sharedDriveName:
if not GM.Globals[GM.ADMIN_DRIVE]: try:
_, GM.Globals[GM.ADMIN_DRIVE] = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail()) sharedDriveName = callGAPI(drive.drives(), 'get',
if GM.Globals[GM.ADMIN_DRIVE]: throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.NOT_FOUND],
try: useDomainAdminAccess=useDomainAdminAccess,
sharedDriveName = callGAPI(GM.Globals[GM.ADMIN_DRIVE].drives(), 'get', driveId=sharedDriveId, fields='name')['name']
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.NOT_FOUND], except (GAPI.notFound, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
useDomainAdminAccess=True,
driveId=sharedDriveId, fields='name')['name']
except (GAPI.notFound, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
sharedDriveName = TEAM_DRIVE
else:
sharedDriveName = TEAM_DRIVE sharedDriveName = TEAM_DRIVE
GM.Globals[GM.MAP_SHAREDDRIVE_ID_TO_NAME][sharedDriveId] = sharedDriveName GM.Globals[GM.MAP_SHAREDDRIVE_ID_TO_NAME][sharedDriveId] = sharedDriveName
return sharedDriveName return sharedDriveName
@@ -52472,7 +52467,7 @@ def _getDriveFileNameFromId(drive, fileId, combineTitleId=True, useDomainAdminAc
if result: if result:
fileName = result['name'] fileName = result['name']
if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE): if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE):
fileName = _getSharedDriveNameFromId(result['driveId']) fileName = _getSharedDriveNameFromId(drive, result['driveId'])
if combineTitleId: if combineTitleId:
fileName += '('+fileId+')' fileName += '('+fileId+')'
return (fileName, _getEntityMimeType(result), result['mimeType']) return (fileName, _getEntityMimeType(result), result['mimeType'])
@@ -53554,7 +53549,7 @@ def getFilePaths(drive, fileTree, initialResult, filePathInfo, addParentsToTree=
fullpath=False, showDepth=False, folderPathOnly=False): fullpath=False, showDepth=False, folderPathOnly=False):
def _getParentName(result): def _getParentName(result):
if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE): if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE):
parentName = _getSharedDriveNameFromId(result['driveId']) parentName = _getSharedDriveNameFromId(drive, result['driveId'])
if parentName != TEAM_DRIVE: if parentName != TEAM_DRIVE:
return f'{SHARED_DRIVES}{filePathInfo["delimiter"]}{parentName}' return f'{SHARED_DRIVES}{filePathInfo["delimiter"]}{parentName}'
return result['name'] return result['name']
@@ -54253,9 +54248,9 @@ def showFileInfo(users):
driveId = result.get('driveId') driveId = result.get('driveId')
if driveId: if driveId:
if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE: if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE:
result['name'] = _getSharedDriveNameFromId(driveId) result['name'] = _getSharedDriveNameFromId(drive, driveId)
if DFF.showSharedDriveNames: if DFF.showSharedDriveNames:
result['driveName'] = _getSharedDriveNameFromId(driveId) result['driveName'] = _getSharedDriveNameFromId(drive, driveId)
if showNoParents: if showNoParents:
result.setdefault('parents', []) result.setdefault('parents', [])
if getPermissionsForSharedDrives and driveId and 'permissions' not in result: if getPermissionsForSharedDrives and driveId and 'permissions' not in result:
@@ -54943,7 +54938,7 @@ def extendFileTreeParents(drive, fileTree, fields):
result['parents'] = [ORPHANS] if result.get('ownedByMe', False) and 'sharedWithMeTime' not in result else [SHARED_WITHME] result['parents'] = [ORPHANS] if result.get('ownedByMe', False) and 'sharedWithMeTime' not in result else [SHARED_WITHME]
else: else:
if result['name'] == TEAM_DRIVE: if result['name'] == TEAM_DRIVE:
result['name'] = _getSharedDriveNameFromId(result['driveId']) result['name'] = _getSharedDriveNameFromId(drive, result['driveId'])
result['parents'] = [SHARED_DRIVES] if 'sharedWithMeTime' not in result else [SHARED_WITHME] result['parents'] = [SHARED_DRIVES] if 'sharedWithMeTime' not in result else [SHARED_WITHME]
fileTree[fileId]['info'] = result fileTree[fileId]['info'] = result
fileTree[fileId]['info']['noDisplay'] = True fileTree[fileId]['info']['noDisplay'] = True
@@ -55688,7 +55683,7 @@ def printFileList(users):
if not pmselect and 'permissions' in fileInfo: if not pmselect and 'permissions' in fileInfo:
fileInfo['permissions'] = DLP.GetFileMatchingPermission(fileInfo) fileInfo['permissions'] = DLP.GetFileMatchingPermission(fileInfo)
if DFF.showSharedDriveNames and driveId: if DFF.showSharedDriveNames and driveId:
fileInfo['driveName'] = _getSharedDriveNameFromId(driveId) fileInfo['driveName'] = _getSharedDriveNameFromId(drive, driveId)
if filepath: if filepath:
if not FJQC.formatJSON or not addPathsToJSON: if not FJQC.formatJSON or not addPathsToJSON:
addFilePathsToRow(drive, fileTree, fileInfo, filePathInfo, csvPF, row, addFilePathsToRow(drive, fileTree, fileInfo, filePathInfo, csvPF, row,
@@ -56558,7 +56553,7 @@ def printShowFilePaths(users):
driveId = result.get('driveId') driveId = result.get('driveId')
if driveId: if driveId:
if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE: if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE:
result['name'] = _getSharedDriveNameFromId(driveId) result['name'] = _getSharedDriveNameFromId(drive, driveId)
if returnPathOnly: if returnPathOnly:
if fullpath: if fullpath:
writeStdout(f'{SHARED_DRIVES}/{result["name"]}\n') writeStdout(f'{SHARED_DRIVES}/{result["name"]}\n')
@@ -56648,7 +56643,7 @@ def printFileParentTree(users):
driveId = result.get('driveId') driveId = result.get('driveId')
if driveId: if driveId:
if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE: if result['mimeType'] == MIMETYPE_GA_FOLDER and result['name'] == TEAM_DRIVE:
result['name'] = _getSharedDriveNameFromId(driveId) result['name'] = _getSharedDriveNameFromId(drive, driveId)
result['isRoot'] = True result['isRoot'] = True
result['parents'] = [''] result['parents'] = ['']
fileList.append(result) fileList.append(result)
@@ -56885,7 +56880,7 @@ def printShowFileCounts(users):
if not drive: if not drive:
continue continue
sharedDriveId = fileIdEntity.get('shareddrive', {}).get('driveId', '') sharedDriveId = fileIdEntity.get('shareddrive', {}).get('driveId', '')
sharedDriveName = _getSharedDriveNameFromId(sharedDriveId) if sharedDriveId else '' sharedDriveName = _getSharedDriveNameFromId(drive, sharedDriveId) if sharedDriveId else ''
mimeTypeInfo = {} mimeTypeInfo = {}
userLastModification = _initLastModification() userLastModification = _initLastModification()
gettingEntity = _getGettingEntity(user, fileIdEntity) gettingEntity = _getGettingEntity(user, fileIdEntity)
@@ -57030,7 +57025,7 @@ def printShowDrivelastModifications(users):
if not drive: if not drive:
continue continue
sharedDriveId = fileIdEntity.get('shareddrive', {}).get('driveId', '') sharedDriveId = fileIdEntity.get('shareddrive', {}).get('driveId', '')
sharedDriveName = _getSharedDriveNameFromId(sharedDriveId) if sharedDriveId else '' sharedDriveName = _getSharedDriveNameFromId(drive, sharedDriveId) if sharedDriveId else ''
userLastModification = _initLastModification() userLastModification = _initLastModification()
gettingEntity = _getGettingEntity(user, fileIdEntity) gettingEntity = _getGettingEntity(user, fileIdEntity)
printGettingAllEntityItemsForWhom(Ent.DRIVE_FILE_OR_FOLDER, gettingEntity, i, count) printGettingAllEntityItemsForWhom(Ent.DRIVE_FILE_OR_FOLDER, gettingEntity, i, count)
@@ -57213,7 +57208,7 @@ def printDiskUsage(users):
includeOwner = False includeOwner = False
csvPF.RemoveTitles(['Owner', 'ownedByMe']) csvPF.RemoveTitles(['Owner', 'ownedByMe'])
if topFolder['name'] == TEAM_DRIVE and not topFolder.get('parents'): if topFolder['name'] == TEAM_DRIVE and not topFolder.get('parents'):
topFolder['name'] = _getSharedDriveNameFromId(driveId) topFolder['name'] = _getSharedDriveNameFromId(drive, driveId)
topFolder['path'] = f'{SHARED_DRIVES}{pathDelimiter}{topFolder["name"]}' topFolder['path'] = f'{SHARED_DRIVES}{pathDelimiter}{topFolder["name"]}'
else: else:
topFolder['path'] = topFolder['name'] topFolder['path'] = topFolder['name']
@@ -57653,7 +57648,7 @@ def printShowFileTree(users):
fileId=fileId, fields=fields, supportsAllDrives=True) fileId=fileId, fields=fields, supportsAllDrives=True)
if (fileEntryInfo['mimeType'] == MIMETYPE_GA_FOLDER and fileEntryInfo.get('driveId') and if (fileEntryInfo['mimeType'] == MIMETYPE_GA_FOLDER and fileEntryInfo.get('driveId') and
fileEntryInfo['name'] == TEAM_DRIVE and not fileEntryInfo.get('parents', [])): fileEntryInfo['name'] == TEAM_DRIVE and not fileEntryInfo.get('parents', [])):
fileEntryInfo['name'] = f"{SHARED_DRIVES}/{_getSharedDriveNameFromId(fileId)}" fileEntryInfo['name'] = f"{SHARED_DRIVES}/{_getSharedDriveNameFromId(drive, fileId)}"
if stripCRsFromName: if stripCRsFromName:
fileEntryInfo['name'] = _stripControlCharsFromName(fileEntryInfo['name']) fileEntryInfo['name'] = _stripControlCharsFromName(fileEntryInfo['name'])
if buildTree: if buildTree:
@@ -59294,7 +59289,7 @@ def _getCopyMoveParentInfo(drive, user, i, count, j, jcount, newParentId, statis
result['destParentType'] = DEST_PARENT_MYDRIVE_FOLDER result['destParentType'] = DEST_PARENT_MYDRIVE_FOLDER
else: else:
if result['name'] == TEAM_DRIVE and not result.get('parents', []): if result['name'] == TEAM_DRIVE and not result.get('parents', []):
result['name'] = _getSharedDriveNameFromId(result['driveId']) result['name'] = _getSharedDriveNameFromId(drive, result['driveId'])
result['destParentType'] = DEST_PARENT_SHAREDDRIVE_ROOT result['destParentType'] = DEST_PARENT_SHAREDDRIVE_ROOT
else: else:
result['destParentType'] = DEST_PARENT_SHAREDDRIVE_FOLDER result['destParentType'] = DEST_PARENT_SHAREDDRIVE_FOLDER
@@ -59843,7 +59838,8 @@ def copyDriveFile(users):
# Source at root of Shared Drive? # Source at root of Shared Drive?
sourceMimeType = source['mimeType'] sourceMimeType = source['mimeType']
if sourceMimeType == MIMETYPE_GA_FOLDER and source.get('driveId') and source['name'] == TEAM_DRIVE and not source.get('parents', []): if sourceMimeType == MIMETYPE_GA_FOLDER and source.get('driveId') and source['name'] == TEAM_DRIVE and not source.get('parents', []):
source['name'] = _getSharedDriveNameFromId(source['driveId']) copyMoveOptions['sourceIsMyDriveSharedDrive'] = True
source['name'] = _getSharedDriveNameFromId(drive, source['driveId'])
sourceName = source['name'] sourceName = source['name']
sourceNameId = f"{sourceName}({source['id']})" sourceNameId = f"{sourceName}({source['id']})"
copyMoveOptions['sourceDriveId'] = source.get('driveId') copyMoveOptions['sourceDriveId'] = source.get('driveId')
@@ -60449,6 +60445,7 @@ def moveDriveFile(users):
GAPI.FILE_OWNER_NOT_MEMBER_OF_TEAMDRIVE, GAPI.FILE_OWNER_NOT_MEMBER_OF_TEAMDRIVE,
GAPI.FILE_OWNER_NOT_MEMBER_OF_WRITER_DOMAIN, GAPI.FILE_OWNER_NOT_MEMBER_OF_WRITER_DOMAIN,
GAPI.FILE_WRITER_TEAMDRIVE_MOVE_IN_DISABLED, GAPI.FILE_WRITER_TEAMDRIVE_MOVE_IN_DISABLED,
GAPI.SHARE_OUT_NOT_PERMITTED,
GAPI.TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION, GAPI.TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION,
GAPI.CANNOT_MOVE_TRASHED_ITEM_INTO_TEAMDRIVE, GAPI.CANNOT_MOVE_TRASHED_ITEM_INTO_TEAMDRIVE,
GAPI.CANNOT_MOVE_TRASHED_ITEM_OUT_OF_TEAMDRIVE, GAPI.CANNOT_MOVE_TRASHED_ITEM_OUT_OF_TEAMDRIVE,
@@ -60463,7 +60460,7 @@ def moveDriveFile(users):
_incrStatistic(statistics, STAT_FILE_COPIED_MOVED) _incrStatistic(statistics, STAT_FILE_COPIED_MOVED)
return return
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.unknownError, GAPI.badRequest, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.unknownError, GAPI.badRequest,
GAPI.targetUserRoleLimitedByLicenseRestriction, GAPI.shareOutNotPermitted, GAPI.targetUserRoleLimitedByLicenseRestriction,
GAPI.cannotMoveTrashedItemIntoTeamDrive, GAPI.cannotMoveTrashedItemOutOfTeamDrive, GAPI.cannotMoveTrashedItemIntoTeamDrive, GAPI.cannotMoveTrashedItemOutOfTeamDrive,
GAPI.teamDrivesShortcutFileNotSupported, GAPI.storageQuotaExceeded) as e: GAPI.teamDrivesShortcutFileNotSupported, GAPI.storageQuotaExceeded) as e:
entityActionFailedWarning(kvList, str(e), k, kcount) entityActionFailedWarning(kvList, str(e), k, kcount)
@@ -60613,7 +60610,7 @@ def moveDriveFile(users):
if sourceMimeType == MIMETYPE_GA_FOLDER and source['name'] in [MY_DRIVE, TEAM_DRIVE] and not source.get('parents', []): if sourceMimeType == MIMETYPE_GA_FOLDER and source['name'] in [MY_DRIVE, TEAM_DRIVE] and not source.get('parents', []):
copyMoveOptions['sourceIsMyDriveSharedDrive'] = True copyMoveOptions['sourceIsMyDriveSharedDrive'] = True
if source.get('driveId'): if source.get('driveId'):
source['name'] = _getSharedDriveNameFromId(source['driveId']) source['name'] = _getSharedDriveNameFromId(drive, source['driveId'])
sourceName = source['name'] sourceName = source['name']
sourceNameId = f"{sourceName}({source['id']})" sourceNameId = f"{sourceName}({source['id']})"
copyMoveOptions['sourceDriveId'] = source.get('driveId') copyMoveOptions['sourceDriveId'] = source.get('driveId')
@@ -63057,7 +63054,7 @@ def printEmptyDriveFolders(users):
fileIdEntity['shareddrive'] = {'driveId': sharedDriveId, 'corpora': 'drive', 'includeItemsFromAllDrives': True, 'supportsAllDrives': True} fileIdEntity['shareddrive'] = {'driveId': sharedDriveId, 'corpora': 'drive', 'includeItemsFromAllDrives': True, 'supportsAllDrives': True}
csvPF.AddTitles(['driveId']) csvPF.AddTitles(['driveId'])
csvPF.MoveTitlesToEnd(['name']) csvPF.MoveTitlesToEnd(['name'])
pathList = [f'{SHARED_DRIVES}/{_getSharedDriveNameFromId(sharedDriveId)}'] pathList = [f'{SHARED_DRIVES}/{_getSharedDriveNameFromId(drive, sharedDriveId)}']
else: else:
pathList = [fileEntryInfo['name']] pathList = [fileEntryInfo['name']]
mimeType = fileEntryInfo['mimeType'] mimeType = fileEntryInfo['mimeType']
@@ -63147,7 +63144,7 @@ def deleteEmptyDriveFolders(users):
if 'driveId' in fileEntryInfo: if 'driveId' in fileEntryInfo:
sharedDriveId = fileEntryInfo['driveId'] sharedDriveId = fileEntryInfo['driveId']
fileIdEntity['shareddrive'] = {'driveId': sharedDriveId, 'corpora': 'drive', 'includeItemsFromAllDrives': True, 'supportsAllDrives': True} fileIdEntity['shareddrive'] = {'driveId': sharedDriveId, 'corpora': 'drive', 'includeItemsFromAllDrives': True, 'supportsAllDrives': True}
pathList = [f'{SHARED_DRIVES}/{_getSharedDriveNameFromId(sharedDriveId)}'] pathList = [f'{SHARED_DRIVES}/{_getSharedDriveNameFromId(drive, sharedDriveId)}']
else: else:
pathList = [fileEntryInfo['name']] pathList = [fileEntryInfo['name']]
mimeType = fileEntryInfo['mimeType'] mimeType = fileEntryInfo['mimeType']
@@ -65420,12 +65417,14 @@ SHAREDDRIVE_ACL_ROLES_MAP = {
# (role|roles <SharedDriveACLRoleList>)* # (role|roles <SharedDriveACLRoleList>)*
# [fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]] # [fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]]
# [guiroles [<Boolean>]] [formatjson [quotechar <Character>]] # [guiroles [<Boolean>]] [formatjson [quotechar <Character>]]
# [showitemcountonly]
# gam <UserTypeEntity> show shareddrives # gam <UserTypeEntity> show shareddrives
# [asadmin [shareddriveadminquery|query <QuerySharedDrive>]] # [asadmin [shareddriveadminquery|query <QuerySharedDrive>]]
# [matchname <REMatchPattrn>] [orgunit|org|ou <OrgUnitPath>] # [matchname <REMatchPattrn>] [orgunit|org|ou <OrgUnitPath>]
# (role|roles <SharedDriveACLRoleLIst>)* # (role|roles <SharedDriveACLRoleLIst>)*
# [fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]] # [fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]]
# [guiroles [<Boolean>]] [formatjson] # [guiroles [<Boolean>]] [formatjson]
# [showitemcountonly]
def printShowSharedDrives(users, useDomainAdminAccess=False): def printShowSharedDrives(users, useDomainAdminAccess=False):
def stripNonShowFields(shareddrive): def stripNonShowFields(shareddrive):
if orgUnitIdToPathMap: if orgUnitIdToPathMap:
@@ -65449,7 +65448,7 @@ def printShowSharedDrives(users, useDomainAdminAccess=False):
SHAREDDRIVE_FIELDS_CHOICE_MAP.update(SHAREDDRIVE_LIST_FIELDS_CHOICE_MAP) SHAREDDRIVE_FIELDS_CHOICE_MAP.update(SHAREDDRIVE_LIST_FIELDS_CHOICE_MAP)
showOrgUnitPaths = True showOrgUnitPaths = True
orgUnitIdToPathMap = None orgUnitIdToPathMap = None
guiRoles = False guiRoles = showItemCountOnly = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -65479,6 +65478,9 @@ def printShowSharedDrives(users, useDomainAdminAccess=False):
showOrgUnitPaths = not getBoolean() showOrgUnitPaths = not getBoolean()
elif myarg == 'guiroles': elif myarg == 'guiroles':
guiRoles = getBoolean() guiRoles = getBoolean()
elif myarg == 'showitemcountonly':
showItemCountOnly = True
showOrgUnitPaths = False
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if query and not useDomainAdminAccess: if query and not useDomainAdminAccess:
@@ -65548,6 +65550,9 @@ def printShowSharedDrives(users, useDomainAdminAccess=False):
jcount = len(matchedFeed) jcount = len(matchedFeed)
if jcount == 0: if jcount == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC) setSysExitRC(NO_ENTITIES_FOUND_RC)
if showItemCountOnly:
writeStdout(f'{jcount}\n')
return
if not csvPF: if not csvPF:
if not FJQC.formatJSON: if not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count) entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count)
@@ -65578,13 +65583,15 @@ def doPrintShowSharedDrives():
# gam print oushareddrives [todrive <ToDriveAttribute>*] # gam print oushareddrives [todrive <ToDriveAttribute>*]
# [ou|org|orgunit <OrgUnitPath>] # [ou|org|orgunit <OrgUnitPath>]
# [formatjson [quotechar <Character>]] # [formatjson [quotechar <Character>]]
# [showitemcountonly]
# gam show oushareddrives # gam show oushareddrives
# [ou|org|orgunit <OrgUnitPath>] # [ou|org|orgunit <OrgUnitPath>]
# [formatjson] # [formatjson]
# [showitemcountonly]
def doPrintShowOrgunitSharedDrives(): def doPrintShowOrgunitSharedDrives():
def _getOrgUnitSharedDriveInfo(shareddrive): def _getOrgUnitSharedDriveInfo(shareddrive):
shareddrive['driveId'] = shareddrive['name'].rsplit(';')[1] shareddrive['driveId'] = shareddrive['name'].rsplit(';')[1]
shareddrive['driveName'] = _getSharedDriveNameFromId(shareddrive['driveId']) shareddrive['driveName'] = _getSharedDriveNameFromId(drive, shareddrive['driveId'], True)
shareddrive['orgUnitPath'] = orgUnitPath shareddrive['orgUnitPath'] = orgUnitPath
def _showOrgUnitSharedDrive(shareddrive, j, jcount, FJQC): def _showOrgUnitSharedDrive(shareddrive, j, jcount, FJQC):
@@ -65598,23 +65605,26 @@ def doPrintShowOrgunitSharedDrives():
printEntity([Ent.MEMBER_URI, shareddrive['memberUri']]) printEntity([Ent.MEMBER_URI, shareddrive['memberUri']])
printEntity([Ent.SHAREDDRIVE_ID, shareddrive['driveId']]) printEntity([Ent.SHAREDDRIVE_ID, shareddrive['driveId']])
printEntity([Ent.SHAREDDRIVE_NAME, shareddrive['driveName']]) printEntity([Ent.SHAREDDRIVE_NAME, shareddrive['driveName']])
printEntity([Ent.ORGANIZATIONAL_UNIT, shareddrive['orgUnit']]) printEntity([Ent.ORGANIZATIONAL_UNIT, shareddrive['orgUnitPath']])
Ind.Decrement() Ind.Decrement()
ci = buildGAPIObject(API.CLOUDIDENTITY_ORGUNITS_BETA) ci = buildGAPIObject(API.CLOUDIDENTITY_ORGUNITS_BETA)
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
_, GM.Globals[GM.ADMIN_DRIVE] = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail()) _, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
if not GM.Globals[GM.ADMIN_DRIVE]: if drive is None:
return return
csvPF = CSVPrintFile(['name', 'type', 'member', 'memberUri', 'driveId', 'driveName', 'orgUnitPath']) if Act.csvFormat() else None csvPF = CSVPrintFile(['name', 'type', 'member', 'memberUri', 'driveId', 'driveName', 'orgUnitPath']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
orgUnitPath = '/' orgUnitPath = '/'
showItemCountOnly = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters() csvPF.GetTodriveParameters()
elif myarg in {'ou', 'org', 'orgunit'}: elif myarg in {'ou', 'org', 'orgunit'}:
orgUnitPath = getString(Cmd.OB_ORGUNIT_ITEM) orgUnitPath = getString(Cmd.OB_ORGUNIT_ITEM)
elif myarg == 'showitemcountonly':
showItemCountOnly = True
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if csvPF and FJQC.formatJSON: if csvPF and FJQC.formatJSON:
@@ -65629,6 +65639,9 @@ def doPrintShowOrgunitSharedDrives():
jcount = len(sds) jcount = len(sds)
if jcount == 0: if jcount == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC) setSysExitRC(NO_ENTITIES_FOUND_RC)
if showItemCountOnly:
writeStdout(f'{jcount}\n')
return
if not csvPF: if not csvPF:
if not FJQC.formatJSON: if not FJQC.formatJSON:
entityPerformActionNumItems([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], jcount, Ent.SHAREDDRIVE) entityPerformActionNumItems([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], jcount, Ent.SHAREDDRIVE)
@@ -65683,13 +65696,13 @@ def copySyncSharedDriveACLs(users, useDomainAdminAccess=False):
if not drive: if not drive:
continue continue
if not srcFileIdEntity.get('shareddrivename'): if not srcFileIdEntity.get('shareddrivename'):
srcFileIdEntity['shareddrivename'] = _getSharedDriveNameFromId(srcFileIdEntity['shareddrive']['driveId']) srcFileIdEntity['shareddrivename'] = _getSharedDriveNameFromId(drive, srcFileIdEntity['shareddrive']['driveId'])
if tgtFileIdEntity.get('shareddrivename'): if tgtFileIdEntity.get('shareddrivename'):
if not _convertSharedDriveNameToId(drive, user, i, count, tgtFileIdEntity, useDomainAdminAccess): if not _convertSharedDriveNameToId(drive, user, i, count, tgtFileIdEntity, useDomainAdminAccess):
continue continue
tgtFileIdEntity['shareddrive']['corpora'] = 'drive' tgtFileIdEntity['shareddrive']['corpora'] = 'drive'
else: else:
tgtFileIdEntity['shareddrivename'] = _getSharedDriveNameFromId(tgtFileIdEntity['shareddrive']['driveId']) tgtFileIdEntity['shareddrivename'] = _getSharedDriveNameFromId(drive, tgtFileIdEntity['shareddrive']['driveId'])
statistics = _initStatistics() statistics = _initStatistics()
copyMoveOptions['sourceDriveId'] = srcFileIdEntity['shareddrive']['driveId'] copyMoveOptions['sourceDriveId'] = srcFileIdEntity['shareddrive']['driveId']
copyMoveOptions['destDriveId'] = tgtFileIdEntity['shareddrive']['driveId'] copyMoveOptions['destDriveId'] = tgtFileIdEntity['shareddrive']['driveId']

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved. # Copyright (C) 2025 Ross Scroggs All Rights Reserved.
# #
# All Rights Reserved. # All Rights Reserved.
# #
@@ -260,12 +260,12 @@ SMTP_HOST = 'smtp_host'
SMTP_USERNAME = 'smtp_username' SMTP_USERNAME = 'smtp_username'
# SMTP password # SMTP password
SMTP_PASSWORD = 'smtp_password' SMTP_PASSWORD = 'smtp_password'
# Time Zone
TIMEZONE = 'timezone'
## Minimum TLS Version required for HTTPS connections ## Minimum TLS Version required for HTTPS connections
TLS_MIN_VERSION = 'tls_min_version' TLS_MIN_VERSION = 'tls_min_version'
## Maximum TLS Version used for HTTPS connections ## Maximum TLS Version used for HTTPS connections
TLS_MAX_VERSION = 'tls_max_version' TLS_MAX_VERSION = 'tls_max_version'
# Time Zone
TIMEZONE = 'timezone'
# Clear basic filter when updating an existing sheet # Clear basic filter when updating an existing sheet
TODRIVE_CLEARFILTER = 'todrive_clearfilter' TODRIVE_CLEARFILTER = 'todrive_clearfilter'
# Use client access for todrive # Use client access for todrive
@@ -431,9 +431,9 @@ Defaults = {
SMTP_HOST: '', SMTP_HOST: '',
SMTP_USERNAME: '', SMTP_USERNAME: '',
SMTP_PASSWORD: '', SMTP_PASSWORD: '',
TIMEZONE: 'utc',
TLS_MIN_VERSION: 'TLSv1_3', TLS_MIN_VERSION: 'TLSv1_3',
TLS_MAX_VERSION: '', TLS_MAX_VERSION: '',
TIMEZONE: 'utc',
TODRIVE_CLEARFILTER: FALSE, TODRIVE_CLEARFILTER: FALSE,
TODRIVE_CLIENTACCESS: FALSE, TODRIVE_CLIENTACCESS: FALSE,
TODRIVE_CONVERSION: TRUE, TODRIVE_CONVERSION: TRUE,
@@ -599,9 +599,9 @@ VAR_INFO = {
SMTP_HOST: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, SMTP_HOST: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SMTP_USERNAME: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, SMTP_USERNAME: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SMTP_PASSWORD: {VAR_TYPE: TYPE_PASSWORD, VAR_LIMITS: (0, None)}, SMTP_PASSWORD: {VAR_TYPE: TYPE_PASSWORD, VAR_LIMITS: (0, None)},
TIMEZONE: {VAR_TYPE: TYPE_TIMEZONE},
TLS_MIN_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MIN_VERSION', VAR_CHOICES: TLS_CHOICE_MAP}, TLS_MIN_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MIN_VERSION', VAR_CHOICES: TLS_CHOICE_MAP},
TLS_MAX_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MAX_VERSION', VAR_CHOICES: TLS_CHOICE_MAP}, TLS_MAX_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MAX_VERSION', VAR_CHOICES: TLS_CHOICE_MAP},
TIMEZONE: {VAR_TYPE: TYPE_TIMEZONE},
TODRIVE_CLEARFILTER: {VAR_TYPE: TYPE_BOOLEAN}, TODRIVE_CLEARFILTER: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_CLIENTACCESS: {VAR_TYPE: TYPE_BOOLEAN}, TODRIVE_CLIENTACCESS: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_CONVERSION: {VAR_TYPE: TYPE_BOOLEAN}, TODRIVE_CONVERSION: {VAR_TYPE: TYPE_BOOLEAN},

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved. # Copyright (C) 2025 Ross Scroggs All Rights Reserved.
# #
# All Rights Reserved. # All Rights Reserved.
# #
@@ -72,6 +72,7 @@ DOMAIN_POLICY = 'domainPolicy'
DOWNLOAD_QUOTA_EXCEEDED = 'downloadQuotaExceeded' DOWNLOAD_QUOTA_EXCEEDED = 'downloadQuotaExceeded'
DUPLICATE = 'duplicate' DUPLICATE = 'duplicate'
EVENT_DURATION_EXCEEDS_LIMIT = 'eventDurationExceedsLimit' EVENT_DURATION_EXCEEDS_LIMIT = 'eventDurationExceedsLimit'
EVENT_TYPE_RESTRICTION = 'eventTypeRestriction'
EXPIRATION_DATES_MUST_BE_IN_THE_FUTURE = 'expirationDatesMustBeInTheFuture' EXPIRATION_DATES_MUST_BE_IN_THE_FUTURE = 'expirationDatesMustBeInTheFuture'
EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS = 'expirationDateNotAllowedForSharedDriveMembers' EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS = 'expirationDateNotAllowedForSharedDriveMembers'
FAILED_PRECONDITION = 'failedPrecondition' FAILED_PRECONDITION = 'failedPrecondition'
@@ -457,6 +458,8 @@ class duplicate(Exception):
pass pass
class eventDurationExceedsLimit(Exception): class eventDurationExceedsLimit(Exception):
pass pass
class eventTypeRestriction(Exception):
pass
class expirationDatesMustBeInTheFuture(Exception): class expirationDatesMustBeInTheFuture(Exception):
pass pass
class expirationDateNotAllowedForSharedDriveMembers(Exception): class expirationDateNotAllowedForSharedDriveMembers(Exception):
@@ -725,6 +728,7 @@ REASON_EXCEPTION_MAP = {
DOWNLOAD_QUOTA_EXCEEDED: downloadQuotaExceeded, DOWNLOAD_QUOTA_EXCEEDED: downloadQuotaExceeded,
DUPLICATE: duplicate, DUPLICATE: duplicate,
EVENT_DURATION_EXCEEDS_LIMIT: eventDurationExceedsLimit, EVENT_DURATION_EXCEEDS_LIMIT: eventDurationExceedsLimit,
EVENT_TYPE_RESTRICTION: eventTypeRestriction,
EXPIRATION_DATES_MUST_BE_IN_THE_FUTURE: expirationDatesMustBeInTheFuture, EXPIRATION_DATES_MUST_BE_IN_THE_FUTURE: expirationDatesMustBeInTheFuture,
EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS: expirationDateNotAllowedForSharedDriveMembers, EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS: expirationDateNotAllowedForSharedDriveMembers,
FAILED_PRECONDITION: failedPrecondition, FAILED_PRECONDITION: failedPrecondition,

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved. # Copyright (C) 2025 Ross Scroggs All Rights Reserved.
# #
# All Rights Reserved. # All Rights Reserved.
# #
@@ -25,8 +25,6 @@
# Some commands want to set a non-zero return code but not bail # Some commands want to set a non-zero return code but not bail
# GAM admin user from oauth2.txt or oauth2service.json # GAM admin user from oauth2.txt or oauth2service.json
ADMIN = 'admn' ADMIN = 'admn'
# Drive service for admin; used to look up Shared Drive Names
ADMIN_DRIVE = 'addr'
# Number/length of API call retries # Number/length of API call retries
API_CALLS_RETRY_DATA = 'rtry' API_CALLS_RETRY_DATA = 'rtry'
# GAM cache directory. If no_cache is True, this variable will be set to None # GAM cache directory. If no_cache is True, this variable will be set to None
@@ -220,7 +218,6 @@ REDIRECT_QUEUE_EOF = 'eof'
# #
Globals = { Globals = {
ADMIN: None, ADMIN: None,
ADMIN_DRIVE: None,
API_CALLS_RETRY_DATA: {}, API_CALLS_RETRY_DATA: {},
CACHE_DIR: None, CACHE_DIR: None,
CACHE_DISCOVERY_ONLY: True, CACHE_DISCOVERY_ONLY: True,

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved. # Copyright (C) 2025 Ross Scroggs All Rights Reserved.
# #
# All Rights Reserved. # All Rights Reserved.
# #
@@ -504,13 +504,15 @@ TO = 'To'
TO_LC = 'to' TO_LC = 'to'
TO_MAXIMUM_OF = 'to maximum of' TO_MAXIMUM_OF = 'to maximum of'
TO_SET_UP_GOOGLE_CHAT = """ TO_SET_UP_GOOGLE_CHAT = """
To set up Google Chat for your API project, please go to: To set up Google Chat for your current project, please go to:
{0} {0}
and follow the instructions at: and follow the instructions at:
https://github.com/GAM-team/GAM/wiki/Chat-Bot#set-up-a-chat-bot https://github.com/GAM-team/GAM/wiki/Chat-Bot#set-up-a-chat-bot
You'll use projects/{1}/topics/no-topic in Connection settings Cloud Pub/Sub Topic Name
""" """
TOTAL_ITEMS_IN_ENTITY = 'Total {0} in {1}' TOTAL_ITEMS_IN_ENTITY = 'Total {0} in {1}'
TRIMMED_MESSAGE_FROM_LENGTH_TO_MAXIMUM = 'Trimmed message of length {0} to maximum length {1}' TRIMMED_MESSAGE_FROM_LENGTH_TO_MAXIMUM = 'Trimmed message of length {0} to maximum length {1}'

View File

@@ -10,6 +10,5 @@ httplib2>=0.22.0
lxml>=5.4.0 lxml>=5.4.0
passlib>=1.7.4 passlib>=1.7.4
pathvalidate>=3.2.3 pathvalidate>=3.2.3
pyscard==2.2.1
python-dateutil python-dateutil
yubikey-manager>=5.6.1 yubikey-manager>=5.6.1

View File

@@ -37,7 +37,6 @@ install_requires =
lxml >= 5.4.0 lxml >= 5.4.0
passlib >= 1.7.4 passlib >= 1.7.4
pathvalidate >= 3.2.3 pathvalidate >= 3.2.3
pyscard == 2.2.1
python-dateutil python-dateutil
yubikey-manager >= 5.6.1 yubikey-manager >= 5.6.1

View File

@@ -64,6 +64,7 @@ Verify the following steps:
* If groups are used to authenticate access, make sure the super admin is in one of the groups * If groups are used to authenticate access, make sure the super admin is in one of the groups
* Collapse "Service status" * Collapse "Service status"
* Expand "Cloud Resource Manager API settings" * Expand "Cloud Resource Manager API settings"
* Select the OU in the left that contains the super admin you'll be using
* Make sure that "Allow users to create projects" is checked * Make sure that "Allow users to create projects" is checked
Verify that all scopes are available: Verify that all scopes are available:

View File

@@ -10,6 +10,46 @@ 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 See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.07.13
Added option `showitemcountonly` to `gam [<UserTypeEntity>] print|show shareddrives` that causes GAM to display the
number of Shared Drives on stdout; no CSV file is written.
### 7.07.12
Fixed bug in `gam print|show oushareddrives` that caused a trap.
Improved getting Shared Drive names from IDs when accessing Shared Drives in external workspaces.
### 7.07.11
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`
to handle the following error:
```
ERROR: 400: badRequest - Bad Request
```
Updated `gam <UserTypeEntity> move drivefile` to handle the following error:
```
ERROR: 400: shareOutNotPermitted
```
### 7.07.10
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`
to handle the following error:
```
ERROR: 400: eventTypeRestriction - Attendees cannot be added to 'fromGmail' event with this visibility setting.
```
### 7.07.09
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events <UserCalendarEntity>`
to handle the following error:
```
gamlib.glgapi.serviceNotAvailable: Authentication backend unavailable.
```
### 7.07.08 ### 7.07.08
Fixed bug in `gam <UserTypeEntity> print filelist ... countsonly` that issued an Fixed bug in `gam <UserTypeEntity> print filelist ... countsonly` that issued an

View File

@@ -335,6 +335,11 @@ gam update group group@domain.com whoCanViewMembership ALL_MEMBERS_CAN_VIEW whoC
Group: group@domain.com, Updated Group: group@domain.com, Updated
``` ```
If you are entering a valid combination but an error message is returned, do the following and then re-issue your command.
```
gam update group group@domain.com whoCanViewMembership ALL_IN_DOMAIN_CAN_VIEW whoCanDiscoverGroup ALL_IN_DOMAIN_CAN_DISCOVER
```
## Manage groups ## Manage groups
These commands allow you to create, update and delete groups. These commands allow you to create, update and delete groups.

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$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version 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 WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.07.08 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.07.13 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.5 x86_64 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:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.07.08 - https://github.com/GAM-team/GAM - pythonsource GAM 7.07.13 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -12,8 +12,9 @@
- [Delete a Shared Drive](#delete-a-shared-drive) - [Delete a Shared Drive](#delete-a-shared-drive)
- [Change Shared Drive visibility](#change-shared-drive-visibility) - [Change Shared Drive visibility](#change-shared-drive-visibility)
- [Display Shared Drives](#display-shared-drives) - [Display Shared Drives](#display-shared-drives)
- [Display List of Shared Drives in an Organizational Unit other than /](#display-list-of-shared-drives-in-an-organizational-unit-other-than-) - [Display Shared Drive Counts](#display-shared-drive-counts)
- [Display List of Shared Drives in an Organizational Unit](#display-list-of-shared-drives-in-an-organizational-unit) - [Display List of Shared Drives in an Organizational Unit](#display-list-of-shared-drives-in-an-organizational-unit)
- [Display Count of Shared Drives in an Organizational Unit](#display-count-of-shared-drives-in-an-organizational-unit)
- [Display all Shared Drives with no members](#display-all-shared-drives-with-no-members) - [Display all Shared Drives with no members](#display-all-shared-drives-with-no-members)
- [Display all Shared Drives with no organizers](#display-all-shared-drives-with-no-organizers) - [Display all Shared Drives with no organizers](#display-all-shared-drives-with-no-organizers)
- [Display all Shared Drives with a specific organizer](#display-all-shared-drives-with-a-specific-organizer) - [Display all Shared Drives with a specific organizer](#display-all-shared-drives-with-a-specific-organizer)
@@ -416,6 +417,36 @@ gam print teamdrives query "memberCount = 0"
gam print teamdrives query "organizerCount = 0" gam print teamdrives query "organizerCount = 0"
``` ```
## Display Shared Drive Counts
Display the number of Shared Drives.
```
gam [<UserTypeEntity>] show|print shareddrives
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
showitemcountonly
```
By default, all Shared Drives are counted; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
Example
```
$ gam print shareddrives showitemcountonly
Getting all Shared Drives, may take some time on a large Google Workspace Account...
Got 12 Shared Drives...
12
```
The `Getting` and `Got` messages are written to stderr, the count is writtem to stdout.
To retrieve the count with `showitemcountonly`:
```
Linux/MacOS
count=$(gam print shareddrives showitemcountonly)
Windows PowerShell
count = & gam print shareddrives showitemcountonly
```
## Display all Shared Drives with a specific organizer ## Display all Shared Drives with a specific organizer
Substitute actual email address for `organizer@domain.com`. Substitute actual email address for `organizer@domain.com`.
``` ```
@@ -428,18 +459,9 @@ Substitute actual email address for `organizer@domain.com`.
gam config csv_output_header_filter "id,name" print teamdriveacls pm emailaddress organizer@domain.com role organizer em pma skip pmselect gam config csv_output_header_filter "id,name" print teamdriveacls pm emailaddress organizer@domain.com role organizer em pma skip pmselect
``` ```
## Display List of Shared Drives in an Organizational Unit other than /
Get the orgUnitID of OU / and use it (without the id:) in the print|show command. Adjust fields as desired.
```
gam info ou / nousers
gam show teamdrives query "orgUnitId!='00gjdgxs2p9cxyz'" fields id,name,orgunit,createdtime
gam print teamdrives query "orgUnitId!='00gjdgxs2p9cxyz'" fields id,name,orgunit,createdtime
```
## Display List of Shared Drives in an Organizational Unit ## Display List of Shared Drives in an Organizational Unit
Get the orgUnitID of the desired OU and use it (without the id:) in the print|show command. Adjust fields as desired. Get the orgUnitID of the desired OU and use it (without the id:) in the print|show command. Adjust fields as desired.
``` ```
gam info ou <OrgUnitPath> nousers
gam show teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime gam show teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime
gam print teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime gam print teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime
``` ```
@@ -453,6 +475,31 @@ gam print oushareddrives [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
``` ```
## Display Count of Shared Drives in an Organizational Unit
```
gam print|show oushareddrives
[ou|org|orgunit <OrgUnitPath>]
showitemcountonly
```
`<OrgUnitPath>` defaults to `"/"`.
Example
```
$ gam print oushareddrives showitemcountonly
Getting all Shared Drives for /, may take some time on a large Organizational Unit...
Got 9 Shared Drives for /...
9
```
The `Getting` and `Got` messages are written to stderr, the count is writtem to stdout.
To retrieve the count with `showitemcountonly`:
```
Linux/MacOS
count=$(gam print oushareddrives showitemcountonly)
Windows PowerShell
count = & gam print oushareddrives showitemcountonly
```
## Manage Shared Drive access ## Manage Shared Drive access
These commands are used to manage the ACLs on Shared Drives themselves, not the files/folders on the Shared Drives. These commands are used to manage the ACLs on Shared Drives themselves, not the files/folders on the Shared Drives.

View File

@@ -662,7 +662,7 @@ When moving a folder you can use the `retainsourcefolders` option to cause GAM t
Moving a Drive folder to a Shared Drive is not directly supported by the API; GAM has to make a copy of the folder on the Shared Drive and Moving a Drive folder to a Shared Drive is not directly supported by the API; GAM has to make a copy of the folder on the Shared Drive and
recursively adjust the files/folders within it to point to the new parent folder. Once the original folder is emptied, it is deleted unless `retainsourcefolders` is specified. recursively adjust the files/folders within it to point to the new parent folder. Once the original folder is emptied, it is deleted unless `retainsourcefolders` is specified.
### Move content of a Shared Drive to another Shared Drive ## Move content of a Shared Drive to another Shared Drive
Suppose you have a source Shared Drive with ID 0AC_1AB with multiple files and folders, and want to move all of its content to the target Shared Drive with ID 0AE_9ZX. Suppose you have a source Shared Drive with ID 0AC_1AB with multiple files and folders, and want to move all of its content to the target Shared Drive with ID 0AE_9ZX.
The following command will change the parents of the top level files and folders from 0AC_1AB to 0AE_9ZX; the sub files and folders will move along with their top level folder. The following command will change the parents of the top level files and folders from 0AC_1AB to 0AE_9ZX; the sub files and folders will move along with their top level folder.
@@ -676,3 +676,19 @@ If you want the source Shared Drive with ID 0AC_1AB to be contained in a top lev
``` ```
gam user user@domain.com move drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX gam user user@domain.com move drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX
``` ```
### Inter-workspace moves
Due to a restructuring, you want to move data from Shared Drive A in domaina.com to Shared Drive B in domainb.com.
* Shared Drive A in domaina.com has the following unchecked: `Allow people outside of Domain A to access files`
* Shared Drive B in domainb.com has the following checked: `Allow people outside of Domain B to access files`
* `user@domaina.com` is a manager of both Shared Drives.
```
$ gam user user@domaina move drivefile teamdriveid <SharedDriveAID> teamdriveparentid <SharedDriveBID> mergewithparent
User: user@domaina.com, Move 1 Drive File/Folder
User: user@domaina.com, Drive Folder: Shared Drive A(<SharedDriveAID>), Move(Merge) contents with Drive Folder: Shared Drive B(<SharedDriveBID>)
User: user@domaina.com, Drive File: Filename(<FileID>), Move Failed: Bad Request. User message: "shareOutNotPermitted"
...
User: user@domaina.com, Drive Folder: Shared Drive A(<SharedDriveAID>), Retained
```
To get this to work, you must check `Allow people outside of Domain A to access files` on Shared Drive A in domaina.com

View File

@@ -7,6 +7,7 @@
- [Manage file permissions/sharing](#manage-file-permissionssharing) - [Manage file permissions/sharing](#manage-file-permissionssharing)
- [Display file permissions/sharing](#display-file-permissionssharing) - [Display file permissions/sharing](#display-file-permissionssharing)
- [Delete all ACLs except owner from a file](#delete-all-acls-except-owner-from-a-file) - [Delete all ACLs except owner from a file](#delete-all-acls-except-owner-from-a-file)
- [Delete all ACLs except owner from a user's My Drive](#delete-all-acls-except-owner-from-a-users-my-drive)
- [Change shares to User1 to shares to User2](#change-shares-to-user1-to-shares-to-user2) - [Change shares to User1 to shares to User2](#change-shares-to-user1-to-shares-to-user2)
- [Map All ACLs from an old domain to a new domain](#map-all-acls-from-an-old-domain-to-a-new-domain) - [Map All ACLs from an old domain to a new domain](#map-all-acls-from-an-old-domain-to-a-new-domain)
@@ -318,13 +319,23 @@ gam redirect csv ./TeamDriveACLs.csv multiprocess csv ./TeamDrives.csv gam print
## Delete all ACLs except owner from a file ## Delete all ACLs except owner from a file
Get the current ACLs. Get the current ACLs.
``` ```
gam redirect csv ./Permissions.csv user <UserItem> print drivefileacls <DriveFileID> oneitemperrow gam redirect csv ./Permissions.csv user user@domain.com print drivefileacls <DriveFileID> oneitemperrow
``` ```
Inspect Permissions.csv, verify that you want to proceed. Inspect Permissions.csv, verify that you want to proceed.
``` ```
gam config csv_input_row_drop_filter "permission.role:regex:(owner)|(organizer)" csv ./Permissions.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~" gam config csv_input_row_drop_filter "permission.role:regex:(owner)|(organizer)" csv ./Permissions.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
``` ```
## Delete all ACLs except owner from a user's My Drive
Get the current ACLs.
```
gam redirect csv ./Permissions.csv user user@domain.com print filelist fields id,name,mimetype,basicpermissions pm not role owner em pmfilter oneitemperrow
```
Inspect Permissions.csv, verify that you want to proceed.
```
gam redirect stdout ./DeletePermissions.txt multiprocess redirect stderr stdout csv Permissions.csv.csv gam user "~Owner" delete drivefileacls "~id" "id:~~permission.id~~"
```
## Change shares to User1 to shares to User2 ## Change shares to User1 to shares to User2
``` ```
# Get files shared to User1 # Get files shared to User1

View File

@@ -11,6 +11,7 @@
- [Delete a Shared Drive](#delete-a-shared-drive) - [Delete a Shared Drive](#delete-a-shared-drive)
- [Change Shared Drive visibility](#change-shared-drive-visibility) - [Change Shared Drive visibility](#change-shared-drive-visibility)
- [Display Shared Drives](#display-shared-drives) - [Display Shared Drives](#display-shared-drives)
- [Display Shared Drive Counts](#display-shared-drive-counts)
- [Manage Shared Drive access](#manage-shared-drive-access) - [Manage Shared Drive access](#manage-shared-drive-access)
- [Display Shared Drive access](#display-shared-drive-access) - [Display Shared Drive access](#display-shared-drive-access)
- [Display Shared Drive access for specific Shared Drives](#display-shared-drive-access-for-specific-shared-drives) - [Display Shared Drive access for specific Shared Drives](#display-shared-drive-access-for-specific-shared-drives)
@@ -356,6 +357,35 @@ When using the `formatjson` option, double quotes are used extensively in the da
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output. The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used. `quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Display Shared Drive Counts
Display the number of Shared Drives.
```
gam <UserTypeEntity> show|print shareddrives
[teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
showitemcountonly
```
By default, all Shared Drives are counted; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
Example
```
$ gam user user@domain.com print shareddrives showitemcountonly
Getting all Shared Drives for user@domain.com
Got 4 Shared Drives for user@domain.com ...
4
```
The `Getting` and `Got` messages are written to stderr, the count is writtem to stdout.
To retrieve the count with `showitemcountonly`:
```
Linux/MacOS
count=$(gam user user@domain.com print shareddrives showitemcountonly)
Windows PowerShell
count = & gam user user@domain.com print shareddrives showitemcountonly
```
## Manage Shared Drive access ## Manage Shared Drive access
These commands must be issued by a user with Shared Drive permission role organizer. These commands must be issued by a user with Shared Drive permission role organizer.
### Process single ACLs. ### Process single ACLs.

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.07.08 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.07.13 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAM 7.07.08 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.07.13 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -27,7 +27,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 Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAM 7.07.08 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.07.13 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 7.07.08 Latest: 7.07.13
echo $? echo $?
1 1
``` ```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
7.07.08 7.07.13
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 7.07.08 - https://github.com/GAM-team/GAM GAM 7.07.13 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64

View File

@@ -287,7 +287,7 @@ csv_output_users_audit
Default: False Default: False
customer_id customer_id
Google Customer ID Google Customer ID
Default: Blank Default: my_customer
Environment variable: CUSTOMER_ID Environment variable: CUSTOMER_ID
debug_level debug_level
If debug_level > 0, turn on API debugging output. If debug_level > 0, turn on API debugging output.
@@ -321,7 +321,7 @@ drive_v3_native_names
email_batch_size email_batch_size
When archiving, printing, showing, trashing, untrashing, marking as spam Gmail messages. When archiving, printing, showing, trashing, untrashing, marking as spam Gmail messages.
how many should be processed in each batch how many should be processed in each batch
Default: 100 Default: 50
Range: 1 - 100 Range: 1 - 100
enable_dasa enable_dasa
Enable/disable Delegated Admin Service Account API Access Enable/disable Delegated Admin Service Account API Access
@@ -384,7 +384,7 @@ message_batch_size
message_max_results message_max_results
When retrieving lists of Gmail messages from API, When retrieving lists of Gmail messages from API,
how many should be retrieved in each API call how many should be retrieved in each API call
Default: 1000 Default: 500
Range: 1 - 10000 Range: 1 - 10000
mobile_max_results mobile_max_results
When retrieving lists of Mobile devices from API, When retrieving lists of Mobile devices from API,
@@ -416,8 +416,10 @@ no_short_urls
the shortened URL redirects to the long URL. the shortened URL redirects to the long URL.
When True, the long scopes URLs in `gam oauth create` and When True, the long scopes URLs in `gam oauth create` and
`gam <UserTypeEntity> check|update serviceaccount` will be used as is. `gam <UserTypeEntity> check|update serviceaccount` will be used as is.
Default: True
no_verify_ssl no_verify_ssl
Disable SSL certificate validation Disable SSL certificate validation
Default: False
num_tbatch_threads num_tbatch_threads
Number of threads for gam tbatch Number of threads for gam tbatch
Default: 2 Default: 2