Compare commits

...

5 Commits

Author SHA1 Message Date
Ross Scroggs
3006d8dfe4 added gam print shareddriveorganizers 2025-05-31 15:03:13 -07:00
Ross Scroggs
f9ed16e2e3 Update Shared-Drives.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-30 17:16:29 -07:00
Ross Scroggs
9999adfb3a Update Users-Gmail-Delegates.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
CodeQL / Analyze (python) (push) Has been cancelled
2025-05-30 10:46:04 -07:00
Ross Scroggs
f09a1e1bd6 Added option oneuserperrow to gam print devices 2025-05-30 06:22:49 -07:00
Ross Scroggs
a95da4e2ea Added option oneuserperrow to gam print devices 2025-05-30 06:22:30 -07:00
10 changed files with 304 additions and 24 deletions

View File

@@ -1383,7 +1383,7 @@ gam show projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
[states all|active|deleterequested] [showiampolicies 0|1|3]
gam print projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>] [todrive <ToDriveAttribute>*]
[states all|active|deleterequested] [showiampolicies 0|1|3 [onememberperrow]]
[delimiter <Character>]] [[formatjson [quotechar <Character>]]
[delimiter <Character>] [[formatjson [quotechar <Character>]]
gam info currentprojectid
gam create|add svcacct [[admin] <EmailAddress>] [<ProjectIDEntity>]
@@ -4119,7 +4119,7 @@ gam print devices [todrive <ToDriveAttribute>*]
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
[orderby <DeviceOrderByFieldName> [ascending|descending]]
[all|company|personal|nocompanydevices|nopersonaldevices]
[nodeviceusers]
[nodeviceusers|oneuserperrow]
[formatjson [quotechar <Character>]]
[showitemcountonly]
@@ -4819,6 +4819,16 @@ gam show shareddrives
[fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]]
[formatjson] [noorgunits [<Boolean>]]
gam print shareddriveorganizers [todrive <ToDriveAttribute>*]
[shareddriveadminquery|query <QuerySharedDrive>]
[orgunit|org|ou <OrgUnitPath>]
[matchname <REMatchPattern>]
[domainlist <DomainList>]
[includetypes <OrganizerTypeList>]
[oneorganizer [<Boolean>]]
[shownorganizerdrives [false|true|only]]
[includefileorganizers [<Boolean>]]
[delimiter <Character>]
gam print oushareddrives [todrive <ToDriveAttribute>*]
[ou|org|orgunit <OrgUnitPath>]
[formatjson [quotechar <Character>]]
@@ -8326,6 +8336,17 @@ gam <UserTypeEntity> show shareddrives
[fields <SharedDriveFieldNameList>] [noorgunits [<Boolean>]]
[formatjson]
gam <UserTypeEntity> print shareddriveorganizers [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[orgunit|org|ou <OrgUnitPath>]
[matchname <REMatchPattern>]
[domainlist <DomainList>]
[includetypes <OrganizerTypeList>]
[oneorganizer [<Boolean>]]
[shownorganizerdrives [false|true|only]]
[includefileorganizers [<Boolean>]]
[delimiter <Character>]
# Users - Force Signout and Turn Off 2-Step Verification
gam <UserTypeEntity> signout

View File

@@ -1,3 +1,36 @@
7.08.00
Added the following command that can be used instead of the `GetTeamDriveOrganizers.py` script.
```
gam [<UserTypeEntity>] print shareddriveorganizers [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[orgunit|org|ou <OrgUnitPath>]
[matchname <REMatchPattern>]
[domainlist <DomainList>]
[includetypes <OrganizerTypeList>]
[oneorganizer [<Boolean>]]
[shownorganizerdrives [false|true|only]]
[includefileorganizers [<Boolean>]]
[delimiter <Character>]
```
The command defaults match the script defaults:
* `domainlist` - All domains
* `includetypes` - user,groups
* `oneorganizer` - False
* `shownoorganizerdrives` - True
* `includefileorganizers` - False
For example, to get a single organizer from your domain for all Shared Drives including no organizer drives:
```
gam redirect csv ./TeamDriveOrganizers.csv print shareddriveorganizers domainlist mydomain.com includetypes user oneorganizer shownoorganizerdrives
```
7.07.17
Added option `oneuserperrow` to `gam print devices` to have each of a
device's users displayed on a separate row with all of the other device fields.
7.07.16
Added `chromeostype`, `diskspaceusage` and `faninfo` to `<CrOSFieldName>` for use in `gam info|print cros`.

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.07.16'
__version__ = '7.08.00'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -17102,11 +17102,11 @@ DATA_TRANSFER_SORT_TITLES = ['id', 'requestTime', 'oldOwnerUserEmail', 'newOwner
# gam print datatransfers|transfers [todrive <ToDriveAttribute>*]
# [olduser|oldowner <UserItem>] [newuser|newowner <UserItem>]
# [status <String>] [delimiter <Character>]]
# [status <String>] [delimiter <Character>]
# (addcsvdata <FieldName> <String>)*
# gam show datatransfers|transfers
# [olduser|oldowner <UserItem>] [newuser|newowner <UserItem>]
# [status <String>] [delimiter <Character>]]
# [status <String>] [delimiter <Character>]
def doPrintShowDataTransfers():
dt = buildGAPIObject(API.DATATRANSFER)
apps = getTransferApplications(dt)
@@ -29587,7 +29587,7 @@ DEVICE_ORDERBY_CHOICE_MAP = {
# <DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
# [orderby <DeviceOrderByFieldName> [ascending|descending]]
# [all|company|personal|nocompanydevices|nopersonaldevices]
# [nodeviceusers]
# [nodeviceusers|oneuserperrow]
# [formatjson [quotechar <Character>]]
# [showitemcountonly]
def doPrintCIDevices():
@@ -29603,7 +29603,7 @@ def doPrintCIDevices():
queries = [None]
view, entityType = DEVICE_VIEW_CHOICE_MAP['all']
getDeviceUsers = True
showItemCountOnly = False
oneUserPerRow = showItemCountOnly = False
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -29618,6 +29618,8 @@ def doPrintCIDevices():
view, entityType = DEVICE_VIEW_CHOICE_MAP[myarg]
elif myarg == 'nodeviceusers':
getDeviceUsers = False
elif myarg in {'oneuserperrow', 'oneitemperrow'}:
getDeviceUsers = oneUserPerRow = True
elif getFieldsList(myarg, DEVICE_FIELDS_CHOICE_MAP, fieldsList, initialField='name'):
pass
elif getFieldsList(myarg, DEVICEUSER_FIELDS_CHOICE_MAP, userFieldsList, initialField='name', fieldsArg='userfields'):
@@ -29631,6 +29633,8 @@ def doPrintCIDevices():
fields = getItemFieldsFromFieldsList('devices', fieldsList)
userFields = getItemFieldsFromFieldsList('deviceUsers', userFieldsList)
substituteQueryTimes(queries, queryTimes)
if FJQC.formatJSON and oneUserPerRow:
csvPF.SetJSONTitles(['name', 'user.name', 'JSON'])
itemCount = 0
for query in queries:
printGettingAllAccountEntities(entityType, query)
@@ -29672,13 +29676,26 @@ def doPrintCIDevices():
except (GAPI.invalid, GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedWarning([entityType, None], str(e))
for device in devices:
row = flattenJSON(device, timeObjects=DEVICE_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': device['name'],
'JSON': json.dumps(cleanJSON(device, timeObjects=DEVICE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
if not oneUserPerRow or 'users' not in device:
row = flattenJSON(device, timeObjects=DEVICE_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': device['name'],
'JSON': json.dumps(cleanJSON(device, timeObjects=DEVICE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
else:
deviceUsers = device.pop('users')
baserow = flattenJSON(device, timeObjects=DEVICE_TIME_OBJECTS)
for deviceUser in deviceUsers:
row = flattenJSON({'user': deviceUser}, flattened=baserow.copy(), timeObjects=DEVICE_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
device['user'] = deviceUser
csvPF.WriteRowNoFilter({'name': device['name'], 'user.name': deviceUser['name'],
'JSON': json.dumps(cleanJSON(device, timeObjects=DEVICE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
if showItemCountOnly:
writeStdout(f'{itemCount}\n')
return
@@ -66033,6 +66050,159 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
def doPrintShowSharedDriveACLs():
printShowSharedDriveACLs([_getAdminEmail()], True)
PRINT_ORGANIZER_TYPES = {'group', 'user'}
# gam [<UserTypeEntity>] print shareddriveorganizers [todrive <ToDriveAttribute>*]
# [adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
# [matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
# [domainlist <DomainList>]
# [includetypes user|group]
# [oneorganizer [<Boolean>]]
# [shownorganizerdrives false|true|only]
# [includefileorganizers [<Boolean>]]
# [delimiter <Character>]
def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
csvPF = CSVPrintFile(['id', 'name', 'organizers', 'createdTime'], 'sortall')
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
roles = set(['organizer'])
includeTypes = set()
showNoOrganizerDrives = SHOW_NO_PERMISSIONS_DRIVES_CHOICE_MAP['false']
fieldsList = ['role', 'type', 'emailAddress']
cd = orgUnitId = query = matchPattern = None
domainList = []
oneOrganizer = False
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'delimiter':
delimiter = getCharacter()
elif myarg in {'teamdriveadminquery', 'shareddriveadminquery', 'query'}:
queryLocation = Cmd.Location()
query = getString(Cmd.OB_QUERY, minLen=0) or None
if query:
query = mapQueryRelativeTimes(query, ['createdTime'])
elif myarg == 'matchname':
matchPattern = getREPattern(re.IGNORECASE)
elif myarg in {'ou', 'org', 'orgunit'}:
orgLocation = Cmd.Location()
if cd is None:
cd = buildGAPIObject(API.DIRECTORY)
orgUnitPath, orgUnitId = getOrgUnitId(cd)
orgUnitId = orgUnitId[3:]
orgUnitInfo = {'orgUnit': orgUnitPath, 'orgUnitId': orgUnitId}
elif myarg in ADMIN_ACCESS_OPTIONS:
useDomainAdminAccess = True
elif myarg == 'domainlist':
domainList = set(getString(Cmd.OB_DOMAIN_NAME_LIST).replace(',', ' ').lower().split())
elif myarg == 'includetypes':
for itype in getString(Cmd.OB_ORGANIZER_TYPE_LIST).lower().replace(',', ' ').split():
if itype in PRINT_ORGANIZER_TYPES:
includeTypes.add(itype)
else:
invalidChoiceExit(itype, PRINT_ORGANIZER_TYPES, True)
elif myarg == 'oneorganizer':
oneOrganizer = getBoolean()
elif myarg == 'shownoorganizerdrives':
showNoOrganizerDrives = getChoice(SHOW_NO_PERMISSIONS_DRIVES_CHOICE_MAP, defaultChoice=1, mapChoice=True)
elif myarg in {'includefileorganizers', 'includecontentmanagers'}:
if getBoolean():
roles.add('fileOrganizer')
else:
unknownArgumentExit()
if query and not useDomainAdminAccess:
Cmd.SetLocation(queryLocation-1)
usageErrorExit(Msg.ONLY_ADMINISTRATORS_CAN_PERFORM_SHARED_DRIVE_QUERIES)
if orgUnitId is not None:
if not useDomainAdminAccess:
Cmd.SetLocation(orgLocation-1)
usageErrorExit(Msg.ONLY_ADMINISTRATORS_CAN_SPECIFY_SHARED_DRIVE_ORGUNIT)
csvPF.AddTitles(['orgUnit', 'orgUnitId'])
if not includeTypes:
includeTypes = PRINT_ORGANIZER_TYPES
fields = getItemFieldsFromFieldsList('permissions', fieldsList, True)
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, drive = buildGAPIServiceObject(API.DRIVE3, user, i, count)
if not drive:
continue
if useDomainAdminAccess:
printGettingAllAccountEntities(Ent.SHAREDDRIVE, query)
pageMessage = getPageMessage()
else:
printGettingAllEntityItemsForWhom(Ent.SHAREDDRIVE, user, i, count, query)
pageMessage = getPageMessageForWhom()
try:
feed = callGAPIpages(drive.drives(), 'list', 'drives',
pageMessage=pageMessage,
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.INVALID_QUERY, GAPI.INVALID,
GAPI.QUERY_REQUIRES_ADMIN_CREDENTIALS,
GAPI.NO_LIST_TEAMDRIVES_ADMINISTRATOR_PRIVILEGE,
GAPI.FILE_NOT_FOUND],
q=query, useDomainAdminAccess=useDomainAdminAccess,
fields='nextPageToken,drives(id,name,createdTime,orgUnitId)', pageSize=100)
except (GAPI.invalidQuery, GAPI.invalid, GAPI.queryRequiresAdminCredentials,
GAPI.noListTeamDrivesAdministratorPrivilege, GAPI.fileNotFound) as e:
entityActionFailedWarning([Ent.USER, user, Ent.SHAREDDRIVE, None], str(e), i, count)
continue
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userDriveServiceNotEnabledWarning(user, str(e), i, count)
continue
matchFeed = []
jcount = len(feed)
j = 0
for shareddrive in feed:
j += 1
if ((matchPattern is not None and matchPattern.match(shareddrive['name']) is None) or
(orgUnitId is not None and orgUnitId != shareddrive.get('orgUnitId'))):
continue
printGettingAllEntityItemsForWhom(Ent.PERMISSION, shareddrive['name'], j, jcount)
shareddrive['createdTime'] = formatLocalTime(shareddrive['createdTime'])
shareddrive['organizers'] = []
try:
permissions = callGAPIpages(drive.permissions(), 'list', 'permissions',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.DRIVE3_GET_ACL_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
useDomainAdminAccess=useDomainAdminAccess,
fileId=shareddrive['id'], fields=fields, supportsAllDrives=True)
for permission in permissions:
if permission['type'] in includeTypes and permission['role'] in roles:
if domainList:
_, domain = permission['emailAddress'].lower().split('@', 1)
if domain not in domainList:
continue
shareddrive['organizers'].append(permission['emailAddress'])
if oneOrganizer:
break
if not shareddrive['organizers']:
if showNoOrganizerDrives == 0: # no organizers and showNoOrganizerDrives False - ignore
continue
matchFeed.append(shareddrive) # no organizers and showNoOrganizerDrives Only/True - keep
continue
if showNoOrganizerDrives < 0: # organizers and showNoOrganizerDrives Only/True - ignore
continue
matchFeed.append(shareddrive)
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError,
GAPI.insufficientAdministratorPrivileges, GAPI.insufficientFilePermissions,
GAPI.unknownError, GAPI.invalid):
pass
if len(matchFeed) == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC)
for shareddrive in matchFeed:
row = {'id': shareddrive['id'], 'name': shareddrive['name'],
'organizers': delimiter.join(shareddrive['organizers']),
'createdTime': shareddrive['createdTime']}
if orgUnitId:
row.update(orgUnitInfo)
csvPF.WriteRowTitles(row)
if csvPF:
csvPF.writeCSVfile('SharedDrive Organizers')
def doPrintSharedDriveOrganizers():
printSharedDriveOrganizers([_getAdminEmail()], True)
LOOKERSTUDIO_ASSETTYPE_CHOICE_MAP = {
'report': ['REPORT'],
'datasource': ['DATA_SOURCE'],
@@ -75919,6 +76089,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_SCHEMA: doPrintShowUserSchemas,
Cmd.ARG_SHAREDDRIVE: doPrintShowSharedDrives,
Cmd.ARG_SHAREDDRIVEACLS: doPrintShowSharedDriveACLs,
Cmd.ARG_SHAREDDRIVEORGANIZERS: doPrintSharedDriveOrganizers,
Cmd.ARG_SITE: deprecatedDomainSites,
Cmd.ARG_SITEACL: deprecatedDomainSites,
Cmd.ARG_SITEACTIVITY: deprecatedDomainSites,
@@ -76267,6 +76438,7 @@ MAIN_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_TEAMDRIVES: Cmd.ARG_SHAREDDRIVE,
Cmd.ARG_TEAMDRIVEACLS: Cmd.ARG_SHAREDDRIVEACLS,
Cmd.ARG_TEAMDRIVEINFO: Cmd.ARG_SHAREDDRIVEINFO,
Cmd.ARG_TEAMDRIVEORGANIZERS: Cmd.ARG_SHAREDDRIVEORGANIZERS,
Cmd.ARG_TEAMDRIVETHEMES: Cmd.ARG_SHAREDDRIVETHEMES,
Cmd.ARG_TOKENS: Cmd.ARG_TOKEN,
Cmd.ARG_TRANSFER: Cmd.ARG_DATATRANSFER,
@@ -76959,6 +77131,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_SENDAS: printShowSendAs,
Cmd.ARG_SHAREDDRIVE: printShowSharedDrives,
Cmd.ARG_SHAREDDRIVEACLS: printShowSharedDriveACLs,
Cmd.ARG_SHAREDDRIVEORGANIZERS: printSharedDriveOrganizers,
Cmd.ARG_SHEET: infoPrintShowSheets,
Cmd.ARG_SHEETRANGE: printShowSheetRanges,
Cmd.ARG_SIGNATURE: printShowSignature,
@@ -77316,6 +77489,7 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_TEAMDRIVES: Cmd.ARG_SHAREDDRIVE,
Cmd.ARG_TEAMDRIVEACLS: Cmd.ARG_SHAREDDRIVEACLS,
Cmd.ARG_TEAMDRIVEINFO: Cmd.ARG_SHAREDDRIVEINFO,
Cmd.ARG_TEAMDRIVEORGANIZERS: Cmd.ARG_SHAREDDRIVEORGANIZERS,
Cmd.ARG_TEAMDRIVETHEMES: Cmd.ARG_SHAREDDRIVETHEMES,
Cmd.ARG_THREADS: Cmd.ARG_THREAD,
Cmd.ARG_TOKENS: Cmd.ARG_TOKEN,

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
# Copyright (C) 2025 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
@@ -755,6 +755,7 @@ class GamCLArgs():
ARG_SHAREDDRIVES = 'shareddrives'
ARG_SHAREDDRIVEACLS = 'shareddriveacls'
ARG_SHAREDDRIVEINFO = 'shareddriveinfo'
ARG_SHAREDDRIVEORGANIZERS = 'shareddriveorganizers'
ARG_SHAREDDRIVETHEMES = 'shareddrivethemes'
ARG_SHEET = 'sheet'
ARG_SHEETS = 'sheets'
@@ -784,6 +785,7 @@ class GamCLArgs():
ARG_TEAMDRIVES = 'teamdrives'
ARG_TEAMDRIVEACLS = 'teamdriveacls'
ARG_TEAMDRIVEINFO = 'teamdriveinfo'
ARG_TEAMDRIVEORGANIZERS = 'teamdriveorganizers'
ARG_TEAMDRIVETHEMES = 'teamdrivethemes'
ARG_THREAD = 'thread'
ARG_THREADS = 'threads'
@@ -964,6 +966,7 @@ class GamCLArgs():
OB_MOBILE_ENTITY = 'MobileEntity'
OB_NETWORK_ID = 'networkID'
OB_NAME = 'Name'
OB_ORGANIZER_TYPE_LIST = 'OrganizerTypeList'
OB_ORGUNIT_ENTITY = 'OrgUnitEntity'
OB_ORGUNIT_ITEM = 'OrgUnitItem'
OB_ORGUNIT_PATH = 'OrgUnitPath'

View File

@@ -210,7 +210,7 @@ gam print devices [todrive <ToDriveAttribute>*]
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
[orderby <DeviceOrderByFieldName> [ascending|descending]]
[all|company|personal|nocompanydevices|nopersonaldevices]
[nodeviceusers]
[nodeviceusers|oneuserperrow]
[formatjson [quotechar <Character>]]
```
By default, all devices are displayed; use the query options to limit the display.
@@ -231,6 +231,9 @@ Select the view of devices to display:
By default, Gam makes additional API calls to display the device users for the devices;
use `nodeviceuser` to suppress making the additional calls.
By default, when device users are displayed, they are all displayed on one row;
use `oneuserperrow` to have each of a device's users displayed on a separate row with all of the other device fields.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.

View File

@@ -10,6 +10,11 @@ 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.07.17
Added option `oneuserperrow` to `gam print devices` to have each of a
device's users displayed on a separate row with all of the other device fields.
### 7.07.16
Added `chromeostype`, `diskspaceusage` and `faninfo` to `<CrOSFieldName>` for use in `gam info|print cros`.

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.07.16 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.07.17 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 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.07.16 - https://github.com/GAM-team/GAM - pythonsource
GAM 7.07.17 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -30,6 +30,7 @@
- [Display ACLs for Shared Drives with all organizers outside of your domain](#display-acls-for-shared-drives-with-all-organizers-outside-of-your-domain)
- [Display ACLs for Shared Drives with all ACLs outside of your domain](#display-acls-for-shared-drives-with-all-acls-outside-of-your-domain)
- [Clean up scammed Shared Drives](#clean-up-scammed-shared-drives)
- [Delete old empty Shared Drives](#delete-old-empty-shared-drives)
## API documentation
* [Drive API - Drives](https://developers.google.com/drive/api/reference/rest/v3/drives)
@@ -791,3 +792,37 @@ This is not reversible, proceed with caution.
```
gam redirect stdout ./DeleteSharedDrives.txt multiprocess redirect stderr stdout csv ./SharedDriveACLsAllExternal.csv gam delete teamdrive "~id" allowitemdeletion
```
## Delete old empty Shared Drives
```
# Get a list of Shared Drives created before one year ago; alter date<-1y as required
gam config csv_output_row_filter "createdTime:date<-1y" redirect csv ./TeamDrives.csv print teamdrives fields id,name,createdtime
# You'll need a list of Shared Drive IDs and organizers; get ACLs for Shared Drives from above
gam redirect csv ./TeamDriveACLs.csv multiprocess csv ./TeamDrives.csv gam print drivefileacls "~id" fields id,emailaddress,role,type,deleted
# Customize script: https://github.com/taers232c/GAM-Scripts3/blob/master/GetTeamDriveOrganizers.py
DOMAIN_LIST = ['yourdomain.org']
INCLUDE_TYPES = {
'user': True,
'group': False,
}
ONE_ORGANIZER = True
SHOW_NO_ORGANIZER_DRIVES = True
INCLUDE_FILE_ORGANIZERS = False
# Run script
python GetTeamDriveOrganizers.py TeamDriveACLs.csv TeamDrives.csv TeamDriveOrganizers.csv
# Inspect TeamDriveOrganizers.csv, you'll have to deal with Shared Drives with no organizer/manager
# Get old empty Shared Drives
gam config num_threads 10 csv_input_row_filter "organizers:regex:^.+$" csv_output_row_filter "Total:count=0" redirect csv ./OldEmptySharedDrives.csv multiprocess redirect stderr - multiprocess csv ./TeamDriveOrganizers.csv gam user "~organizers" print filecounts select teamdriveid "~id" showsize
# Inspect OldEmptySharedDrives.csv, if you're confident of the results, proceed
# Delete old empty Shared Drives
gam redirect stdout ./DeleteOldEmptySharedDrives.txt multiprocess redirect stderr stdout csv ./OldEmptySharedDrives.csv gam user "~User" delete shareddrive "~id"
```

View File

@@ -1,4 +1,5 @@
# Users - Gmail - Delegates
- [Notes](#notes)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Aliases](#aliases)
@@ -8,6 +9,11 @@
- [Display Gmail delegates](#display-gmail-delegates)
- [Delete all delegates for a user](#delete-all-delegates-for-a-user)
## Notes
To use Gmail delegation, the delegator and delagatee must be in org units where
mail delegation is enabled. In the admin console, go to Apps/Google Workspace/Gmail/User Settings.
## API documentation
* [Gmail API - Delegates](https://developers.google.com/gmail/api/v1/reference/users.settings.delegates)
* [Delegation Notes](https://support.google.com/a/answer/7223765)

View File

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