mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-10 17:21:36 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce7e506c29 | ||
|
|
a9d8ac27d3 | ||
|
|
58912ae7ac | ||
|
|
f882439cbd | ||
|
|
56bc52aa28 | ||
|
|
416125abac | ||
|
|
904292ded3 | ||
|
|
5f55bcc812 | ||
|
|
b35de53f5d | ||
|
|
3c34948678 | ||
|
|
0be73db60b | ||
|
|
5b57b51384 | ||
|
|
139896ec3b | ||
|
|
9b52c0bf18 | ||
|
|
b9c9b59f7b | ||
|
|
0e0877e084 | ||
|
|
bdce13e97b | ||
|
|
9c4a17e12c | ||
|
|
a64f4d4a46 | ||
|
|
c396a3b901 | ||
|
|
78453a15af | ||
|
|
a0282ba775 |
@@ -4860,8 +4860,8 @@ gam <UserTypeEntity> sendemail from <EmailAddress>
|
||||
allowcontentmanagerstosharefolders|
|
||||
copyrequireswriterpermission|
|
||||
domainusersonly|
|
||||
downloadrestrictedforreaders|
|
||||
downloadrestrictedforwriters|
|
||||
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
|
||||
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
|
||||
drivemembersonly|teammembersonly|
|
||||
sharingfoldersrequiresorganizerpermission
|
||||
|
||||
@@ -4878,7 +4878,7 @@ In these commands, the Google administrator named in oauth2.txt is used.
|
||||
gam show shareddrivethemes
|
||||
gam create shareddrive <Name>
|
||||
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[movetoorgunitdelay <Integer>]
|
||||
@@ -4932,7 +4932,7 @@ In these commands, you specify an administrator and then indicate that you want
|
||||
|
||||
gam <UserTypeEntity> create shareddrive <Name> adminaccess
|
||||
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[movetoorgunitdelay <Integer>]
|
||||
@@ -4966,7 +4966,7 @@ In these commands, you specify a user, administrator access is not used.
|
||||
|
||||
gam <UserTypeEntity> create shareddrive <Name>
|
||||
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[movetoorgunitdelay <Integer>]
|
||||
@@ -6597,6 +6597,7 @@ gam <UserTypeEntity> print chatemojis [todrive <ToDriveAttribute>*]
|
||||
(folderColorRgb <ColorValue>)|
|
||||
(indexabletext <String>)|
|
||||
(inheritedpermissionsdisabled [<Boolean>])|
|
||||
(itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>])|
|
||||
(keeprevisionforever|pinned)|
|
||||
(lastviewedbyme <Time>)|
|
||||
(mimetype <MimeType>)|
|
||||
@@ -7071,6 +7072,10 @@ gam <UserTypeEntity> collect orphans
|
||||
contentrestrictions.restrictiontime|
|
||||
contentrestrictions.type
|
||||
|
||||
<DriveDownloadRestrictionsSubfieldName> ::=
|
||||
downloadrestrictions.itemdownloadrestriction|
|
||||
downloadrestrictions.effectivedownloadrestrictionwithcontext
|
||||
|
||||
<ClassificationLabelInfoSubfieldName> ::=
|
||||
labels.id| # modifiedByMe
|
||||
labels.revisionid| # copyRequiresWriterPermission
|
||||
@@ -7164,6 +7169,8 @@ gam <UserTypeEntity> collect orphans
|
||||
copyrequireswriterpermission|
|
||||
createddate|createdtime|
|
||||
description|
|
||||
downloadrestictions|
|
||||
<DriveDownloadRestrictionsSubfieldName>|
|
||||
driveid|
|
||||
drivename|
|
||||
editable|
|
||||
@@ -8475,8 +8482,8 @@ gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
||||
allowcontentmanagerstosharefolders|
|
||||
copyrequireswriterpermission|
|
||||
domainusersonly|
|
||||
downloadrestrictedforreaders|
|
||||
downloadrestrictedforwriters|
|
||||
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
|
||||
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
|
||||
drivemembersonly|teammembersonly|
|
||||
sharingfoldersrequiresorganizerpermission
|
||||
|
||||
@@ -8491,13 +8498,13 @@ sharingfoldersrequiresorganizerpermission true
|
||||
gam <UserTypeEntity> show shareddrivethemes
|
||||
gam <UserTypeEntity> create shareddrive <Name>
|
||||
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
|
||||
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [name <Name>]
|
||||
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>]
|
||||
gam <UserTypeEntity> delete shareddrive <SharedDriveEntity>
|
||||
[allowitemdeletion]
|
||||
@@ -8696,3 +8703,11 @@ gam <UserTypeEntity> print youtubechannels [todrive <ToDriveAttribute>*]
|
||||
gam create|add verify|verification <DomainName>
|
||||
gam update verify|verification <DomainName> cname|txt|text|site|file
|
||||
gam info verify|verification
|
||||
|
||||
# Web Resourses and Sites
|
||||
|
||||
gam <UserTypeEntity> show webresources
|
||||
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
|
||||
gam <UserTypeEntity> show webmastersites
|
||||
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
|
||||
```
|
||||
|
||||
@@ -1,3 +1,68 @@
|
||||
7.17.03
|
||||
|
||||
Fixed bug in gam <UserItem> print|show chatspaces asadmin fields <ChatSpaceFieldNameList>` that caused a trap
|
||||
when `isplayname` was not in `<ChatSpaceFieldNameList>`.
|
||||
|
||||
7.17.02
|
||||
|
||||
Updated `gam <UserTypeEntity> print|show webmastersites` to handle the following error
|
||||
that occurs if you haven't updated your project to include the Google Search Console API.
|
||||
```
|
||||
ERROR: 403: permissionDenied - Google Search Console API has not been used in project 111055363999 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/searchconsole.googleapis.com/overview?project=111055363999 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
|
||||
```
|
||||
|
||||
7.17.01
|
||||
|
||||
Fixed bug in `gam <UserTypeEntity> show webmastersites` that caused a trap.
|
||||
|
||||
7.17.00
|
||||
|
||||
Added commands to discover Sites and WebResources that managed users (previously unmanaged) may have access to for better governance and visibility.
|
||||
These are special purpose commands and will not generally be used.
|
||||
```
|
||||
gam <UserTypeEntity> show webresources
|
||||
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
|
||||
gam <UserTypeEntity> show webmastersites
|
||||
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
|
||||
```
|
||||
|
||||
7.16.01
|
||||
|
||||
The Drive API now supports setting download restrictions on individual files.
|
||||
|
||||
Added `downloadrestictions` and `<DriveDownloadRestrictionsSubfieldName>` to `<DriveFieldName>`.
|
||||
```
|
||||
<DriveDownloadRestrictionsSubfieldName> ::=
|
||||
downloadrestrictions.itemdownloadrestriction|
|
||||
downloadrestrictions.effectivedownloadrestrictionwithcontext
|
||||
```
|
||||
|
||||
Added `itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>]`
|
||||
to `<DriveFileAttribute>`.
|
||||
|
||||
From the Drive API documentation:
|
||||
```
|
||||
itemDownloadRestriction - The download restriction of the file applied directly by the owner or organizer. This does not take into account shared drive settings or DLP rules.
|
||||
effectiveDownloadRestrictionWithContext - Output only. The effective download restriction applied to this file. This considers all restriction settings and DLP rules.
|
||||
restrictedForReaders - Whether download and copy is restricted for readers.
|
||||
restrictedForWriters - Whether download and copy is restricted for writers. If true, download is also restricted for readers.
|
||||
```
|
||||
|
||||
7.16.00
|
||||
|
||||
Removed `drive_v3_native_names` from `gam.cfg`; GAM now only uses Drive API v3 fields names on output.
|
||||
If you had `drive_v3_native_names = False` in `gam.cfg` or are updating from Legacy GAM:
|
||||
|
||||
* See: https://github.com/GAM-team/GAM/wiki/Drive-REST-API-v3
|
||||
|
||||
7.15.01
|
||||
|
||||
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
|
||||
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
|
||||
and `downloadrestrictedforwriters` were supported (they are still supported).
|
||||
|
||||
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
|
||||
|
||||
7.15.00
|
||||
|
||||
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`
|
||||
|
||||
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
||||
"""
|
||||
|
||||
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
||||
__version__ = '7.15.00'
|
||||
__version__ = '7.17.03'
|
||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
#pylint: disable=wrong-import-position
|
||||
@@ -5688,19 +5688,22 @@ def getUserEmailFromID(uid, cd):
|
||||
try:
|
||||
result = callGAPI(cd.users(), 'get',
|
||||
throwReasons=GAPI.USER_GET_THROW_REASONS,
|
||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||
userKey=uid, fields='primaryEmail')
|
||||
return result.get('primaryEmail')
|
||||
except (GAPI.userNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
||||
GAPI.badRequest, GAPI.backendError, GAPI.systemError):
|
||||
GAPI.badRequest, GAPI.backendError, GAPI.systemError, GAPI.serviceNotAvailable):
|
||||
return None
|
||||
|
||||
def getGroupEmailFromID(uid, cd):
|
||||
try:
|
||||
result = callGAPI(cd.groups(), 'get',
|
||||
throwReasons=GAPI.GROUP_GET_THROW_REASONS,
|
||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||
groupKey=uid, fields='email')
|
||||
return result.get('email')
|
||||
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden, GAPI.badRequest):
|
||||
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
||||
GAPI.badRequest, GAPI.serviceNotAvailable):
|
||||
return None
|
||||
|
||||
def getServiceAccountEmailFromID(account_id, sal=None):
|
||||
@@ -7862,7 +7865,6 @@ class CSVPrintFile():
|
||||
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '')
|
||||
self.SetTimestampColumn(GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN])
|
||||
self.SetFormatJSON(False)
|
||||
self.SetMapDrive3Titles(False)
|
||||
self.SetNodataFields(False, None, None, None, False)
|
||||
self.SetFixPaths(False)
|
||||
self.SetShowPermissionsLast(False)
|
||||
@@ -7932,13 +7934,6 @@ class CSVPrintFile():
|
||||
self.sortTitlesList = self.titlesList[:]
|
||||
self.sortTitlesSet = set(self.sortTitlesList)
|
||||
|
||||
def SetMapDrive3Titles(self, mapDrive3Titles):
|
||||
self.mapDrive3Titles = mapDrive3Titles
|
||||
|
||||
def MapDrive3TitlesToDrive2(self):
|
||||
_mapDrive3TitlesToDrive2(self.titlesList, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
|
||||
self.titlesSet = set(self.titlesList)
|
||||
|
||||
def AddJSONTitle(self, title):
|
||||
self.JSONtitlesSet.add(title)
|
||||
self.JSONtitlesList.append(title)
|
||||
@@ -8974,7 +8969,6 @@ class CSVPrintFile():
|
||||
self.formatJSON, self.JSONtitlesList,
|
||||
self.columnDelimiter, self.noEscapeChar, self.quoteChar,
|
||||
self.sortHeaders, self.timestampColumn,
|
||||
self.mapDrive3Titles,
|
||||
self.fixPaths,
|
||||
self.mapNodataFields,
|
||||
self.nodataFields,
|
||||
@@ -9009,8 +9003,6 @@ class CSVPrintFile():
|
||||
self.MovePermsToEnd()
|
||||
if not self.rows and self.nodataFields is not None:
|
||||
self.FixNodataTitles()
|
||||
if self.mapDrive3Titles:
|
||||
self. MapDrive3TitlesToDrive2()
|
||||
else:
|
||||
self.titlesList = self.headerForce
|
||||
if self.timestampColumn:
|
||||
@@ -9646,11 +9638,10 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
|
||||
csvPF.SetQuoteChar(dataItem[7])
|
||||
csvPF.SetSortHeaders(dataItem[8])
|
||||
csvPF.SetTimestampColumn(dataItem[9])
|
||||
csvPF.SetMapDrive3Titles(dataItem[10])
|
||||
csvPF.SetFixPaths(dataItem[11])
|
||||
csvPF.SetNodataFields(dataItem[12], dataItem[13], dataItem[14], dataItem[15], dataItem[16])
|
||||
csvPF.SetShowPermissionsLast(dataItem[17])
|
||||
csvPF.SetZeroBlankMimeTypeCounts(dataItem[18])
|
||||
csvPF.SetFixPaths(dataItem[10])
|
||||
csvPF.SetNodataFields(dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15])
|
||||
csvPF.SetShowPermissionsLast(dataItem[16])
|
||||
csvPF.SetZeroBlankMimeTypeCounts(dataItem[17])
|
||||
elif dataType == GM.REDIRECT_QUEUE_DATA:
|
||||
csvPF.rows.extend(dataItem)
|
||||
elif dataType == GM.REDIRECT_QUEUE_ARGS:
|
||||
@@ -26949,7 +26940,7 @@ def printShowChatSpaces(users):
|
||||
substituteQueryTimes(queries, queryTimes)
|
||||
pfilter = kwargsCS['query'] = queries[0]
|
||||
kwargsCS['useAdminAccess'] = True
|
||||
sortName = 'displayName'
|
||||
sortName = 'displayName' if 'displayName' in fieldsList else 'name'
|
||||
else:
|
||||
sortName = 'name'
|
||||
for user in users:
|
||||
@@ -46975,8 +46966,8 @@ def doCreateSiteVerification():
|
||||
printKeyValueList(['Meta HTML Header Data', webserver_meta_record['token']])
|
||||
printBlankLine()
|
||||
|
||||
def _showSiteVerificationInfo(site):
|
||||
printKeyValueList(['Site', site['site']['identifier']])
|
||||
def _showSiteVerificationInfo(site, i=0, count=0):
|
||||
printKeyValueListWithCount(['Site', site['site']['identifier']], i, count)
|
||||
Ind.Increment()
|
||||
printKeyValueList(['ID', unquote(site['id'])])
|
||||
printKeyValueList(['Type', site['site']['type']])
|
||||
@@ -47084,11 +47075,87 @@ def doInfoSiteVerification():
|
||||
checkForExtraneousArguments()
|
||||
sites = callGAPIitems(verif.webResource(), 'list', 'items')
|
||||
if sites:
|
||||
count = len(sites)
|
||||
i = 0
|
||||
for site in sorted(sites, key=lambda k: (k['site']['type'], k['site']['identifier'])):
|
||||
_showSiteVerificationInfo(site)
|
||||
i += 1
|
||||
_showSiteVerificationInfo(site, i, count)
|
||||
else:
|
||||
printKeyValueList(['No Sites Verified.'])
|
||||
|
||||
# gam <UserTypeEntity> show webresources
|
||||
# gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
|
||||
def printShowWebResources(users):
|
||||
csvPF = CSVPrintFile(['User', 'site.identifier']) if Act.csvFormat() else None
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
csvPF.GetTodriveParameters()
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
i, count, users = getEntityArgument(users)
|
||||
for user in users:
|
||||
i += 1
|
||||
user, verif = buildGAPIServiceObject(API.SITEVERIFICATION, user, i, count)
|
||||
if not verif:
|
||||
continue
|
||||
sites = callGAPIitems(verif.webResource(), 'list', 'items')
|
||||
jcount = len(sites)
|
||||
if not csvPF:
|
||||
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.WEB_RESOURCE, i, count)
|
||||
Ind.Increment()
|
||||
j = 0
|
||||
for site in sorted(sites, key=lambda k: (k['site']['type'], k['site']['identifier'])):
|
||||
j += 1
|
||||
_showSiteVerificationInfo(site, j, jcount)
|
||||
Ind.Decrement()
|
||||
else:
|
||||
for site in sites:
|
||||
row = flattenJSON(site, flattened={'User': user})
|
||||
csvPF.WriteRowTitles(row)
|
||||
if csvPF:
|
||||
csvPF.writeCSVfile('Web Resources')
|
||||
|
||||
# gam <UserTypeEntity> show webmastersites
|
||||
# gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
|
||||
def printShowWebMasterSites(users):
|
||||
csvPF = CSVPrintFile(['User', 'siteUrl']) if Act.csvFormat() else None
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
csvPF.GetTodriveParameters()
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
i, count, users = getEntityArgument(users)
|
||||
for user in users:
|
||||
i += 1
|
||||
user, searchconsole = buildGAPIServiceObject(API.SEARCHCONSOLE, user, i, count)
|
||||
if not searchconsole:
|
||||
continue
|
||||
try:
|
||||
sites = callGAPIitems(searchconsole.sites(), 'list', 'siteEntry',
|
||||
throwReasons=[GAPI.PERMISSION_DENIED])
|
||||
except GAPI.permissionDenied as e:
|
||||
accessErrorExitNonDirectory(API.SEARCHCONSOLE, str(e))
|
||||
jcount = len(sites)
|
||||
if not csvPF:
|
||||
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.WEB_MASTERSITE, i, count)
|
||||
Ind.Increment()
|
||||
j = 0
|
||||
for site in sorted(sites, key=lambda k: k['siteUrl']):
|
||||
j += 1
|
||||
printKeyValueListWithCount(['Site', site['siteUrl']], j, jcount)
|
||||
Ind.Increment()
|
||||
printKeyValueList(['permissionLevel', site['permissionLevel']])
|
||||
Ind.Decrement()
|
||||
Ind.Decrement()
|
||||
else:
|
||||
for site in sites:
|
||||
row = flattenJSON(site, flattened={'User': user})
|
||||
csvPF.WriteRowTitles(row)
|
||||
if csvPF:
|
||||
csvPF.writeCSVfile('Web Master Sites')
|
||||
|
||||
def checkCourseExists(croom, courseId, i=0, count=0, entityType=Ent.COURSE):
|
||||
courseId = addCourseIdScope(courseId)
|
||||
try:
|
||||
@@ -53829,6 +53896,13 @@ DRIVE_FILE_CONTENT_RESTRICTIONS_CHOICE_MAP = {
|
||||
'ownerrestricted': 'ownerRestricted',
|
||||
}
|
||||
|
||||
DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP = {
|
||||
'downloadrestrictedforreaders': 'restrictedForReaders',
|
||||
'downloadrestrictedforwriters': 'restrictedForWriters',
|
||||
'restrictedforreaders': 'restrictedForReaders',
|
||||
'restrictedforwriters': 'restrictedForWriters',
|
||||
}
|
||||
|
||||
def getDriveFileProperty(visibility=None):
|
||||
key = getString(Cmd.OB_PROPERTY_KEY)
|
||||
value = getString(Cmd.OB_PROPERTY_VALUE, minLen=0) or None
|
||||
@@ -53880,6 +53954,20 @@ def getDriveFileAddRemoveParentAttribute(myarg, parameters):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _getDriveFileDownloadRestrictions(myarg, body):
|
||||
subField = myarg
|
||||
if subField.startswith('downloadrestrictions.'):
|
||||
_, subField = subField.split('.', 1)
|
||||
if subField.startswith('itemdownloadrestriction.'):
|
||||
_, subField = subField.split('.', 1)
|
||||
if subField == 'itemdownloadrestriction':
|
||||
subField = getChoice(DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP)
|
||||
if subField in DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP:
|
||||
body.setdefault('downloadRestrictions', {'itemDownloadRestriction': {}})
|
||||
body['downloadRestrictions']['itemDownloadRestriction'][DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP[subField]] = getBoolean()
|
||||
return True
|
||||
return False
|
||||
|
||||
def getDriveFileCopyAttribute(myarg, body, parameters):
|
||||
if myarg == 'ignoredefaultvisibility':
|
||||
parameters[DFA_IGNORE_DEFAULT_VISIBILITY] = getBoolean()
|
||||
@@ -53915,6 +54003,8 @@ def getDriveFileCopyAttribute(myarg, body, parameters):
|
||||
else:
|
||||
Cmd.Backup()
|
||||
usageErrorExit(Msg.REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE)
|
||||
elif _getDriveFileDownloadRestrictions(myarg, body):
|
||||
pass
|
||||
elif myarg == 'inheritedpermissionsdisabled':
|
||||
body['inheritedPermissionsDisabled'] = getBoolean()
|
||||
elif myarg == 'property':
|
||||
@@ -54605,11 +54695,6 @@ DRIVEFILE_ORDERBY_CHOICE_MAP = {
|
||||
'viewedbymetime': 'viewedByMeTime',
|
||||
}
|
||||
|
||||
def _mapDrive3TitlesToDrive2(titles, drive3TitlesMap):
|
||||
for i, title in enumerate(titles):
|
||||
if title in drive3TitlesMap:
|
||||
titles[i] = drive3TitlesMap[title]
|
||||
|
||||
def _mapDriveUser(field):
|
||||
if 'me' in field:
|
||||
field['isAuthenticatedUser'] = field.pop('me')
|
||||
@@ -54617,32 +54702,25 @@ def _mapDriveUser(field):
|
||||
field['picture'] = {'url': field.pop('photoLink')}
|
||||
|
||||
def _mapDrivePermissionNames(permission):
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
if 'displayName' in permission:
|
||||
permission['name'] = permission.pop('displayName')
|
||||
if 'expirationTime' in permission:
|
||||
permission['expirationDate'] = formatLocalTime(permission.pop('expirationTime'))
|
||||
if 'allowFileDiscovery' in permission:
|
||||
permission['withLink'] = not permission.pop('allowFileDiscovery')
|
||||
emailAddress = permission.get('emailAddress')
|
||||
if emailAddress:
|
||||
_, permission['domain'] = splitEmailAddress(emailAddress)
|
||||
|
||||
def _mapDriveParents(f_file, parentsSubFields):
|
||||
def _mapDriveInfo(f_file, parentsSubFields, showParentsIdsAsList):
|
||||
if 'parents' in f_file:
|
||||
parents = f_file.pop('parents')
|
||||
if len(parents) == 1 and parents[0] == ORPHANS:
|
||||
return
|
||||
f_file['parents'] = []
|
||||
for parentId in parents:
|
||||
parent = {}
|
||||
if parentsSubFields['id']:
|
||||
parent['id'] = parentId
|
||||
if parentsSubFields['isRoot']:
|
||||
parent['isRoot'] = parentId == parentsSubFields['rootFolderId']
|
||||
f_file['parents'].append(parent)
|
||||
if showParentsIdsAsList:
|
||||
f_file['parentsIds'] = parents
|
||||
elif len(parents) != 1 or parents[0] != ORPHANS:
|
||||
f_file['parents'] = []
|
||||
for parentId in parents:
|
||||
parent = {}
|
||||
if parentsSubFields['id']:
|
||||
parent['id'] = parentId
|
||||
if parentsSubFields['isRoot']:
|
||||
parent['isRoot'] = parentId == parentsSubFields['rootFolderId']
|
||||
f_file['parents'].append(parent)
|
||||
|
||||
def _mapDriveProperties(f_file):
|
||||
appProperties = f_file.pop('appProperties', [])
|
||||
properties = f_file.pop('properties', [])
|
||||
if appProperties:
|
||||
@@ -54654,51 +54732,10 @@ def _mapDriveProperties(f_file):
|
||||
for key, value in sorted(properties.items()):
|
||||
f_file['properties'].append({'key': key, 'value': value, 'visibility': 'PUBLIC'})
|
||||
|
||||
def _mapDriveFieldNames(f_file, user, parentsSubFields, mapToLabels):
|
||||
if mapToLabels:
|
||||
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_LABELS_MAP.items():
|
||||
if attrib in f_file:
|
||||
f_file.setdefault('labels', {})
|
||||
f_file['labels'][v2attrib] = f_file.pop(attrib)
|
||||
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP.items():
|
||||
if attrib in f_file:
|
||||
f_file[v2attrib] = f_file.pop(attrib)
|
||||
capabilities = f_file.get('capabilities')
|
||||
if capabilities:
|
||||
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP.items():
|
||||
if attrib in capabilities:
|
||||
f_file[v2attrib] = capabilities[attrib]
|
||||
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP.items():
|
||||
if attrib in capabilities:
|
||||
capabilities[v2attrib] = capabilities.pop(attrib)
|
||||
if 'spaces' in f_file:
|
||||
f_file['appDataContents'] = 'appDataFolder' in f_file['spaces']
|
||||
if 'lastModifyingUser' in f_file:
|
||||
if 'displayName' in f_file['lastModifyingUser']:
|
||||
f_file['lastModifyingUserName'] = f_file['lastModifyingUser']['displayName']
|
||||
_mapDriveUser(f_file['lastModifyingUser'])
|
||||
if 'owners' in f_file:
|
||||
for owner in f_file['owners']:
|
||||
_mapDriveUser(owner)
|
||||
if 'displayName' in owner:
|
||||
f_file.setdefault('ownerNames', [])
|
||||
f_file['ownerNames'].append(owner['displayName'])
|
||||
_mapDriveUser(f_file.get('sharingUser', {}))
|
||||
_mapDriveParents(f_file, parentsSubFields)
|
||||
_mapDriveProperties(f_file)
|
||||
for permission in f_file.get('permissions', []):
|
||||
if (permission.get('type') == 'user') and (permission.get('emailAddress', '').lower() == user) and ('role' in permission):
|
||||
f_file['userPermission'] = {'id': 'me', 'role': permission['role'], 'type': permission['type']}
|
||||
_mapDrivePermissionNames(permission)
|
||||
|
||||
def _mapDriveRevisionNames(revision):
|
||||
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP.items():
|
||||
if attrib in revision:
|
||||
revision[v2attrib] = revision.pop(attrib)
|
||||
if 'lastModifyingUser' in revision:
|
||||
if 'displayName' in revision['lastModifyingUser']:
|
||||
revision['lastModifyingUserName'] = revision['lastModifyingUser']['displayName']
|
||||
_mapDriveUser(revision['lastModifyingUser'])
|
||||
emailAddress = permission.get('emailAddress')
|
||||
if emailAddress:
|
||||
_, permission['domain'] = splitEmailAddress(emailAddress)
|
||||
|
||||
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
|
||||
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
|
||||
@@ -54722,6 +54759,7 @@ DRIVE_FIELDS_CHOICE_MAP = {
|
||||
'createddate': 'createdTime',
|
||||
'createdtime': 'createdTime',
|
||||
'description': 'description',
|
||||
'downloadrestrictions': 'downloadRestrictions',
|
||||
'driveid': 'driveId',
|
||||
'drivename': 'driveId',
|
||||
'editable': 'capabilities.canEdit',
|
||||
@@ -54868,6 +54906,11 @@ DRIVE_CONTENT_RESTRICTIONS_SUBFIELDS_CHOICE_MAP = {
|
||||
'type': 'type',
|
||||
}
|
||||
|
||||
DRIVE_DOWNLOAD_RESTRICTIONS_SUBFIELDS_CHOICE_MAP = {
|
||||
'itemdownloadrestriction': 'itemDownloadRestriction',
|
||||
'effectivedownloadrestrictionwithcontext': 'effectiveDownloadRestrictionWithContext',
|
||||
}
|
||||
|
||||
DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP = {
|
||||
'id': 'labels(id)',
|
||||
'fields': 'labels(fields)',
|
||||
@@ -54932,6 +54975,7 @@ DRIVE_SHORTCUTDETAILS_SUBFIELDS_CHOICE_MAP = {
|
||||
DRIVE_SUBFIELDS_CHOICE_MAP = {
|
||||
'capabilities': DRIVE_CAPABILITIES_SUBFIELDS_CHOICE_MAP,
|
||||
'contentrestrictions': DRIVE_CONTENT_RESTRICTIONS_SUBFIELDS_CHOICE_MAP,
|
||||
'downloadrestrictions': DRIVE_DOWNLOAD_RESTRICTIONS_SUBFIELDS_CHOICE_MAP,
|
||||
'labelinfo': DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP,
|
||||
'labels': DRIVE_LABEL_CHOICE_MAP,
|
||||
'lastmodifyinguser': DRIVE_SHARINGUSER_SUBFIELDS_CHOICE_MAP,
|
||||
@@ -54949,11 +54993,7 @@ FILEINFO_FIELDS_TITLES = ['name', 'mimeType']
|
||||
FILEPATH_FIELDS_TITLES = ['name', 'id', 'mimeType', 'ownedByMe', 'parents', 'sharedWithMeTime', 'driveId']
|
||||
FILEPATH_FIELDS = ','.join(FILEPATH_FIELDS_TITLES)
|
||||
|
||||
def _getDriveTimeObjects():
|
||||
timeObjects = ['createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime']
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
|
||||
return set(timeObjects)
|
||||
DRIVE_TIME_OBJECTS = {'createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime'}
|
||||
|
||||
def _getDriveFieldSubField(field, fieldsList, parentsSubFields):
|
||||
field, subField = field.split('.', 1)
|
||||
@@ -55150,7 +55190,6 @@ def showFileInfo(users):
|
||||
showNoParents = True
|
||||
includeLabels = ','.join(DFF.includeLabels)
|
||||
pathFields = FILEPATH_FIELDS
|
||||
timeObjects = _getDriveTimeObjects()
|
||||
i, count, users = getEntityArgument(users)
|
||||
for user in users:
|
||||
i += 1
|
||||
@@ -55244,22 +55283,14 @@ def showFileInfo(users):
|
||||
if fullpath:
|
||||
# Save simple parents list as mappings turn it into a list of dicts
|
||||
fpparents = result['parents'][:]
|
||||
if showParentsIdsAsList and 'parents' in result:
|
||||
result['parentsIds'] = result.pop('parents')
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDriveFieldNames(result, user, DFF.parentsSubFields, True)
|
||||
else:
|
||||
_mapDriveParents(result, DFF.parentsSubFields)
|
||||
_mapDriveProperties(result)
|
||||
for permission in result.get('permissions', []):
|
||||
_mapDrivePermissionNames(permission)
|
||||
_mapDriveInfo(result, DFF.parentsSubFields, showParentsIdsAsList)
|
||||
if not FJQC.formatJSON:
|
||||
showJSON(None, result, skipObjects=skipObjects, timeObjects=timeObjects, simpleLists=simpleLists,
|
||||
showJSON(None, result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS, simpleLists=simpleLists,
|
||||
dictObjectsKey={'owners': 'displayName', 'fields': 'id', 'labels': 'id', 'user': 'emailAddress', 'parents': 'id',
|
||||
'permissions': ['name', 'displayName'][GC.Values[GC.DRIVE_V3_NATIVE_NAMES]]})
|
||||
'permissions': 'displayName'})
|
||||
Ind.Decrement()
|
||||
else:
|
||||
printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=timeObjects), ensure_ascii=False, sort_keys=True))
|
||||
printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
|
||||
if fullpath:
|
||||
# Restore simple parents list
|
||||
fileTree[fileId]['info']['parents'] = fpparents[:]
|
||||
@@ -55651,18 +55682,12 @@ FILEREVISIONS_FIELDS_CHOICE_MAP = {
|
||||
'size': 'size',
|
||||
}
|
||||
|
||||
def _getFileRevisionsTimeObjects():
|
||||
timeObjects = ['modifiedTime']
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
|
||||
return set(timeObjects)
|
||||
FILEREVISIONS_TIME_OBJECTS = {'modifiedTime'}
|
||||
|
||||
def _showRevision(revision, timeObjects, i=0, count=0):
|
||||
def _showRevision(revision, i=0, count=0):
|
||||
printEntity([Ent.DRIVE_FILE_REVISION, revision['id']], i, count)
|
||||
Ind.Increment()
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDriveRevisionNames(revision)
|
||||
showJSON(None, revision, ['id'], timeObjects)
|
||||
showJSON(None, revision, ['id'], timeObjects=FILEREVISIONS_TIME_OBJECTS)
|
||||
Ind.Decrement()
|
||||
|
||||
DRIVE_REVISIONS_INDEXED_TITLES = ['revisions']
|
||||
@@ -55686,7 +55711,6 @@ def printShowFileRevisions(users):
|
||||
revisionsEntity = None
|
||||
oneItemPerRow = previewDelete = showTitles = stripCRsFromName = False
|
||||
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
@@ -55704,7 +55728,7 @@ def printShowFileRevisions(users):
|
||||
elif myarg == 'showtitles':
|
||||
showTitles = True
|
||||
if csvPF:
|
||||
csvPF.AddTitles(fileNameTitle)
|
||||
csvPF.AddTitles('name')
|
||||
elif myarg == 'stripcrsfromname':
|
||||
stripCRsFromName = True
|
||||
elif getFieldsList(myarg, FILEREVISIONS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'):
|
||||
@@ -55715,7 +55739,6 @@ def printShowFileRevisions(users):
|
||||
fields = getItemFieldsFromFieldsList('revisions', fieldsList)
|
||||
else:
|
||||
fields = '*'
|
||||
timeObjects = _getFileRevisionsTimeObjects()
|
||||
i, count, users = getEntityArgument(users)
|
||||
for user in users:
|
||||
i += 1
|
||||
@@ -55755,29 +55778,24 @@ def printShowFileRevisions(users):
|
||||
k = 0
|
||||
for revision in results:
|
||||
k += 1
|
||||
_showRevision(revision, timeObjects, k, kcount)
|
||||
_showRevision(revision, k, kcount)
|
||||
Ind.Decrement()
|
||||
elif results:
|
||||
if oneItemPerRow:
|
||||
for revision in results:
|
||||
row = {'Owner': user, 'id': fileId}
|
||||
if showTitles:
|
||||
row[fileNameTitle] = fileName
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDriveRevisionNames(revision)
|
||||
csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=timeObjects))
|
||||
row['name'] = fileName
|
||||
csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=FILEREVISIONS_TIME_OBJECTS))
|
||||
else:
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
for revision in results:
|
||||
_mapDriveRevisionNames(revision)
|
||||
if showTitles:
|
||||
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, fileNameTitle: fileName}, timeObjects=timeObjects))
|
||||
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, 'name': fileName}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
|
||||
else:
|
||||
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=timeObjects))
|
||||
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
|
||||
Ind.Decrement()
|
||||
if csvPF:
|
||||
if oneItemPerRow:
|
||||
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle, 'revision.id'])
|
||||
csvPF.SetSortTitles(['Owner', 'id', 'name', 'revision.id'])
|
||||
else:
|
||||
csvPF.SetSortTitles(['Owner', 'id', 'revisions'])
|
||||
csvPF.SetIndexedTitles(DRIVE_REVISIONS_INDEXED_TITLES)
|
||||
@@ -56587,10 +56605,10 @@ def printFileList(users):
|
||||
def _printFileInfoRow(baserow, fileInfo):
|
||||
row = baserow.copy()
|
||||
if not FJQC.formatJSON:
|
||||
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
|
||||
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
|
||||
simpleLists=simpleLists, delimiter=delimiter))
|
||||
else:
|
||||
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
|
||||
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
|
||||
ensure_ascii=False, sort_keys=True)
|
||||
csvPF.WriteRowTitlesJSONNoFilter(row)
|
||||
|
||||
@@ -56641,15 +56659,7 @@ def printFileList(users):
|
||||
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
|
||||
else:
|
||||
addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly)
|
||||
if showParentsIdsAsList and 'parents' in fileInfo:
|
||||
fileInfo['parentsIds'] = fileInfo.pop('parents')
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDriveFieldNames(fileInfo, user, DFF.parentsSubFields, False)
|
||||
else:
|
||||
_mapDriveParents(fileInfo, DFF.parentsSubFields)
|
||||
_mapDriveProperties(fileInfo)
|
||||
for permission in fileInfo.get('permissions', []):
|
||||
_mapDrivePermissionNames(permission)
|
||||
_mapDriveInfo(fileInfo, DFF.parentsSubFields, showParentsIdsAsList)
|
||||
if showParentsIdsAsList and 'parentsIds' in fileInfo:
|
||||
fileInfo['parents'] = len(fileInfo['parentsIds'])
|
||||
if addCSVData:
|
||||
@@ -56657,24 +56667,24 @@ def printFileList(users):
|
||||
if not countsOnly:
|
||||
if not oneItemPerRow or 'permissions' not in fileInfo:
|
||||
if not FJQC.formatJSON:
|
||||
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
|
||||
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
|
||||
simpleLists=simpleLists, delimiter=delimiter))
|
||||
else:
|
||||
if 'id' in fileInfo:
|
||||
row['id'] = fileInfo['id']
|
||||
if fileNameTitle in fileInfo:
|
||||
row[fileNameTitle] = fileInfo[fileNameTitle]
|
||||
if 'name' in fileInfo:
|
||||
row['name'] = fileInfo['name']
|
||||
if 'owners' in fileInfo:
|
||||
flattenJSON({'owners': fileInfo['owners']}, flattened=row, skipObjects=skipObjects)
|
||||
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
|
||||
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
|
||||
ensure_ascii=False, sort_keys=True)
|
||||
csvPF.WriteRowTitlesJSONNoFilter(row)
|
||||
else:
|
||||
baserow = row.copy()
|
||||
if 'id' in fileInfo:
|
||||
baserow['id'] = fileInfo['id']
|
||||
if fileNameTitle in fileInfo:
|
||||
baserow[fileNameTitle] = fileInfo[fileNameTitle]
|
||||
if 'name' in fileInfo:
|
||||
baserow['name'] = fileInfo['name']
|
||||
if 'owners' in fileInfo:
|
||||
flattenJSON({'owners': fileInfo['owners']}, flattened=baserow, skipObjects=skipObjects)
|
||||
for permission in fileInfo.pop('permissions'):
|
||||
@@ -56688,7 +56698,7 @@ def printFileList(users):
|
||||
_printFileInfoRow(baserow, fileInfo)
|
||||
else:
|
||||
if not countsRowFilter:
|
||||
csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
|
||||
csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
|
||||
simpleLists=simpleLists, delimiter=delimiter), mimeTypeInfo, sizeField)
|
||||
else:
|
||||
mimeTypeInfo.setdefault(fileInfo['mimeType'], {'count': 0, 'size': 0})
|
||||
@@ -56955,12 +56965,6 @@ def printFileList(users):
|
||||
csvPF.AddTitles('paths')
|
||||
csvPF.SetFixPaths(True)
|
||||
includeLabels = ','.join(DFF.includeLabels)
|
||||
timeObjects = _getDriveTimeObjects()
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
fileNameTitle = 'title'
|
||||
csvPF.SetMapDrive3Titles(True)
|
||||
else:
|
||||
fileNameTitle = 'name'
|
||||
csvPF.RemoveTitles(['capabilities'])
|
||||
if DLP.queryTimes and selectSubQuery:
|
||||
for queryTimeName, queryTimeValue in DLP.queryTimes.items():
|
||||
@@ -56980,9 +56984,9 @@ def printFileList(users):
|
||||
if not FJQC.formatJSON:
|
||||
nodataFields = ['Owner']+list(set(DFF.fieldsList)-skipObjects)
|
||||
else:
|
||||
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress']
|
||||
nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
|
||||
else:
|
||||
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress']
|
||||
nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
|
||||
if not FJQC.formatJSON:
|
||||
nodataFields.append('permissions')
|
||||
if filepath:
|
||||
@@ -57162,7 +57166,7 @@ def printFileList(users):
|
||||
if not csvPF.rows:
|
||||
setSysExitRC(NO_ENTITIES_FOUND_RC)
|
||||
if not FJQC.formatJSON:
|
||||
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle])
|
||||
csvPF.SetSortTitles(['Owner', 'id', 'name'])
|
||||
else:
|
||||
if 'JSON' in csvPF.JSONtitlesList:
|
||||
csvPF.MoveJSONTitlesToEnd(['JSON'])
|
||||
@@ -57430,8 +57434,7 @@ def printShowFileComments(users):
|
||||
# [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||
# [followshortcuts [<Boolean>]]
|
||||
def printShowFilePaths(users):
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
csvPF = CSVPrintFile(['Owner', 'id', fileNameTitle, 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
|
||||
csvPF = CSVPrintFile(['Owner', 'id', 'name', 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
fullpath = folderPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False
|
||||
pathDelimiter = '/'
|
||||
@@ -57532,11 +57535,11 @@ def printShowFilePaths(users):
|
||||
if oneItemPerRow:
|
||||
if paths:
|
||||
for path in paths:
|
||||
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name'], 'path': path})
|
||||
csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name'], 'path': path})
|
||||
else:
|
||||
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name']})
|
||||
csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name']})
|
||||
else:
|
||||
csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, fileNameTitle: result['name']}))
|
||||
csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, 'name': result['name']}))
|
||||
except GAPI.fileNotFound:
|
||||
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], Msg.DOES_NOT_EXIST, j, jcount)
|
||||
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
|
||||
@@ -57549,8 +57552,7 @@ def printShowFilePaths(users):
|
||||
# gam <UserTypeEntity> print fileparenttree <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||
# [stripcrsfromname]
|
||||
def printFileParentTree(users):
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', fileNameTitle, 'parentId', 'depth', 'isRoot'], 'sortall')
|
||||
csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', 'name', 'parentId', 'depth', 'isRoot'], 'sortall')
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
stripCRsFromName = False
|
||||
while Cmd.ArgumentsRemaining():
|
||||
@@ -57610,7 +57612,7 @@ def printFileParentTree(users):
|
||||
kcount = len(fileList)
|
||||
isBase = True
|
||||
for result in fileList:
|
||||
csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], fileNameTitle: result['name'],
|
||||
csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], 'name': result['name'],
|
||||
'parentId': result['parents'][0], 'depth': kcount, 'isRoot': result['isRoot']})
|
||||
isBase = False
|
||||
kcount -= 1
|
||||
@@ -58409,7 +58411,7 @@ def printShowFileTree(users):
|
||||
userInfo['index'] += 1
|
||||
row = userInfo.copy()
|
||||
row['depth'] = depth
|
||||
row[fileNameTitle] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name']
|
||||
row['name'] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name']
|
||||
for field in FILETREE_FIELDS_PRINT_ORDER:
|
||||
if showFields[field]:
|
||||
if field == 'parents':
|
||||
@@ -58417,7 +58419,7 @@ def printShowFileTree(users):
|
||||
elif field == 'owners':
|
||||
row[field] = delimiter.join([owner['emailAddress'] for owner in fileEntry.get(field, [])])
|
||||
elif field == 'size':
|
||||
row[fileSize] = fileEntry.get(sizeField, 0)
|
||||
row['size'] = fileEntry.get(sizeField, 0)
|
||||
else:
|
||||
row[field] = fileEntry.get(field, '')
|
||||
csvPF.WriteRow(row)
|
||||
@@ -58518,14 +58520,6 @@ def printShowFileTree(users):
|
||||
unknownArgumentExit()
|
||||
fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)',
|
||||
'shared', sizeField, 'explicitlyTrashed', 'trashed', 'webViewLink']
|
||||
if csvPF:
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
fileNameTitle = 'title'
|
||||
fileSize = 'fileSize'
|
||||
csvPF.SetMapDrive3Titles(True)
|
||||
else:
|
||||
fileNameTitle = 'name'
|
||||
fileSize = 'size'
|
||||
buildTree = (not fileIdEntity
|
||||
or (not fileIdEntity['dict']
|
||||
and not fileIdEntity['query']
|
||||
@@ -58585,7 +58579,7 @@ def printShowFileTree(users):
|
||||
if jcount == 0:
|
||||
continue
|
||||
if csvPF:
|
||||
userInfo = {'User': user, 'index': 0, 'depth': 0, fileNameTitle: ''}
|
||||
userInfo = {'User': user, 'index': 0, 'depth': 0, 'name': ''}
|
||||
j = 0
|
||||
Ind.Increment()
|
||||
for fileId in fileIdEntity['list']:
|
||||
@@ -58745,8 +58739,7 @@ def createDriveFile(users):
|
||||
media_body = getMediaBody(parameters)
|
||||
body['mimeType'] = parameters[DFA_LOCALMIMETYPE]
|
||||
if csvPF:
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
csvPF.SetTitles(['User', fileNameTitle, 'id'])
|
||||
csvPF.SetTitles(['User', 'name', 'id'])
|
||||
if showDetails:
|
||||
csvPF.AddTitles(['parentId', 'mimeType'])
|
||||
if addCSVData:
|
||||
@@ -58806,7 +58799,7 @@ def createDriveFile(users):
|
||||
else:
|
||||
entityActionPerformed(kvList, i, count)
|
||||
else:
|
||||
row = {'User': user, fileNameTitle: result['name'], 'id': result['id']}
|
||||
row = {'User': user, 'name': result['name'], 'id': result['id']}
|
||||
if showDetails:
|
||||
row.update({'parentId': parentId, 'mimeType': result['mimeType']})
|
||||
if addCSVData:
|
||||
@@ -60309,7 +60302,7 @@ def _checkForExistingShortcut(drive, fileId, fileName, parentId):
|
||||
supportsAllDrives=True, includeItemsFromAllDrives=True,
|
||||
q=f"shortcutDetails.targetId = '{fileId}' and trashed = False", fields='files(id,name,parents)')['files']
|
||||
for shortcut in existingShortcuts:
|
||||
if parentId in shortcut['parents'] and fileName == shortcut['name']:
|
||||
if parentId in shortcut.get('parents', []) and fileName == shortcut['name']:
|
||||
return shortcut['id']
|
||||
except (GAPI.invalidQuery, GAPI.invalid, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
|
||||
pass
|
||||
@@ -60362,8 +60355,8 @@ copyReturnItemMap = {
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
def copyDriveFile(users):
|
||||
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
|
||||
row = {'User': user, fileNameTitle: oldName, 'id': oldId,
|
||||
newFileNameTitle: newName, 'newId': newId, 'mimeType': mimeType}
|
||||
row = {'User': user, 'name': oldName, 'id': oldId,
|
||||
'newName': newName, 'newId': newId, 'mimeType': mimeType}
|
||||
if addCSVData:
|
||||
row.update(addCSVData)
|
||||
csvPF.WriteRow(row)
|
||||
@@ -60753,9 +60746,7 @@ def copyDriveFile(users):
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
if csvPF:
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
newFileNameTitle = f'new{fileNameTitle.capitalize()}'
|
||||
csvPF.SetTitles(['User', fileNameTitle, 'id', newFileNameTitle, 'newId', 'mimeType'])
|
||||
csvPF.SetTitles(['User', 'name', 'id', 'newName', 'newId', 'mimeType'])
|
||||
if addCSVData:
|
||||
csvPF.AddTitles(sorted(addCSVData.keys()))
|
||||
i, count, users = getEntityArgument(users)
|
||||
@@ -64155,11 +64146,8 @@ def _getDriveFileACLPrintKeysTimeObjects():
|
||||
printKeys = ['id', 'type', 'emailAddress', 'domain', 'role', 'permissionDetails',
|
||||
'expirationTime', 'photoLink', 'allowFileDiscovery', 'deleted',
|
||||
'pendingOwner', 'view']
|
||||
timeObjects = ['expirationTime']
|
||||
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
|
||||
_mapDrive3TitlesToDrive2(printKeys, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
|
||||
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
|
||||
return (printKeys, set(timeObjects))
|
||||
timeObjects = {'expirationTime'}
|
||||
return (printKeys, timeObjects)
|
||||
|
||||
# DriveFileACL commands utilities
|
||||
def _showDriveFilePermissionJSON(user, fileId, fileName, createdTime, permission, timeObjects):
|
||||
@@ -64251,7 +64239,6 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
|
||||
showDetails = True
|
||||
csvPF = None
|
||||
FJQC = FormatJSONQuoteChar(csvPF)
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
body = {}
|
||||
body['type'] = permType = getChoice(DRIVEFILE_ACL_PERMISSION_TYPES)
|
||||
@@ -64327,7 +64314,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
|
||||
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
|
||||
if csvPF:
|
||||
if showTitles:
|
||||
csvPF.AddTitles(fileNameTitle)
|
||||
csvPF.AddTitles('name')
|
||||
csvPF.SetSortAllTitles()
|
||||
if FJQC.formatJSON:
|
||||
csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
|
||||
@@ -64366,7 +64353,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
|
||||
if csvPF:
|
||||
baserow = {'Owner': user, 'id': fileId}
|
||||
if showTitles:
|
||||
baserow[fileNameTitle] = fileName
|
||||
baserow['name'] = fileName
|
||||
row = baserow.copy()
|
||||
_mapDrivePermissionNames(permission)
|
||||
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
|
||||
@@ -64422,7 +64409,6 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
showDetails = True
|
||||
csvPF = None
|
||||
FJQC = FormatJSONQuoteChar(csvPF)
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
body = {}
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
@@ -64457,7 +64443,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
|
||||
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
|
||||
if csvPF and showTitles:
|
||||
csvPF.AddTitles(fileNameTitle)
|
||||
csvPF.AddTitles('name')
|
||||
csvPF.SetSortAllTitles()
|
||||
if FJQC.formatJSON:
|
||||
csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
|
||||
@@ -64500,7 +64486,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
if csvPF:
|
||||
baserow = {'Owner': user, 'id': fileId}
|
||||
if showTitles:
|
||||
baserow[fileNameTitle] = fileName
|
||||
baserow['name'] = fileName
|
||||
row = baserow.copy()
|
||||
_mapDrivePermissionNames(permission)
|
||||
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
|
||||
@@ -65065,7 +65051,6 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
fieldsList = []
|
||||
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
||||
PM = PermissionMatch()
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
@@ -65084,7 +65069,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
addTitle = getString(Cmd.OB_STRING)
|
||||
showTitles = False
|
||||
if csvPF:
|
||||
csvPF.AddTitles(fileNameTitle)
|
||||
csvPF.AddTitles('name')
|
||||
csvPF.SetSortAllTitles()
|
||||
elif getDriveFilePermissionsFields(myarg, fieldsList):
|
||||
pass
|
||||
@@ -65169,7 +65154,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
else:
|
||||
baserow = {'Owner': user, 'id': fileId}
|
||||
if showTitles or addTitle:
|
||||
baserow[fileNameTitle] = fileName
|
||||
baserow['name'] = fileName
|
||||
if oneItemPerRow:
|
||||
for permission in permissions:
|
||||
_mapDrivePermissionNames(permission)
|
||||
@@ -65736,7 +65721,6 @@ def doPrintShowOwnership():
|
||||
customerId = GC.Values[GC.CUSTOMER_ID]
|
||||
if customerId == GC.MY_CUSTOMER:
|
||||
customerId = None
|
||||
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
|
||||
csvPF = CSVPrintFile('Owner') if Act.csvFormat() else None
|
||||
FJQC = FormatJSONQuoteChar(csvPF)
|
||||
addCSVData = {}
|
||||
@@ -65781,7 +65765,7 @@ def doPrintShowOwnership():
|
||||
else:
|
||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||
if csvPF and not FJQC.formatJSON:
|
||||
csvPF.AddTitles(['id', fileNameTitle, 'type', 'ownerIsSharedDrive', 'driveId', 'event'])
|
||||
csvPF.AddTitles(['id', 'name', 'type', 'ownerIsSharedDrive', 'driveId', 'event'])
|
||||
if addCSVData:
|
||||
csvPF.AddTitles(sorted(addCSVData.keys()))
|
||||
csvPF.SetSortAllTitles()
|
||||
@@ -65814,7 +65798,7 @@ def doPrintShowOwnership():
|
||||
elif event['name'] != 'change_owner' and item['name'] == 'owner':
|
||||
fileInfo['Owner'] = item['value']
|
||||
elif item['name'] == 'doc_title':
|
||||
fileInfo[fileNameTitle] = item['value']
|
||||
fileInfo['name'] = item['value']
|
||||
elif item['name'] == 'doc_type':
|
||||
fileInfo['type'] = item['value']
|
||||
elif item['name'] == 'owner_is_shared_drive':
|
||||
@@ -65827,7 +65811,7 @@ def doPrintShowOwnership():
|
||||
if not csvPF:
|
||||
if not FJQC.formatJSON:
|
||||
printEntityKVList([Ent.OWNER, fileInfo['Owner']],
|
||||
['id', fileInfo['id'], fileNameTitle, fileInfo.get(fileNameTitle, ''),
|
||||
['id', fileInfo['id'], 'name', fileInfo.get('name', ''),
|
||||
'type', fileInfo.get('type', ''),
|
||||
'ownerIsSharedDrive', fileInfo.get('ownerIsSharedDrive', False),
|
||||
'driveId', fileInfo.get('driveId', ''),
|
||||
@@ -65885,6 +65869,10 @@ SHAREDDRIVE_RESTRICTIONS_MAP = {
|
||||
'sharingfoldersrequiresorganizerpermission': 'sharingFoldersRequiresOrganizerPermission',
|
||||
'teammembersonly': 'driveMembersOnly',
|
||||
}
|
||||
SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP = {
|
||||
'restrictedforreaders': 'downloadrestrictedforreaders',
|
||||
'restrictedforwriters': 'downloadrestrictedforwriters',
|
||||
}
|
||||
|
||||
def _getSharedDriveRestrictions(myarg, body):
|
||||
def _setRestriction(restriction):
|
||||
@@ -65899,7 +65887,12 @@ def _getSharedDriveRestrictions(myarg, body):
|
||||
|
||||
if myarg.startswith('restrictions.'):
|
||||
_, subField = myarg.split('.', 1)
|
||||
if subField in SHAREDDRIVE_RESTRICTIONS_MAP:
|
||||
if subField.startswith('downloadrestrictions.'):
|
||||
_, subField = subField.split('.', 1)
|
||||
if subField in SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP:
|
||||
_setRestriction(SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP[subField])
|
||||
return True
|
||||
elif subField in SHAREDDRIVE_RESTRICTIONS_MAP:
|
||||
_setRestriction(subField)
|
||||
return True
|
||||
invalidChoiceExit(subField, SHAREDDRIVE_RESTRICTIONS_MAP, True)
|
||||
@@ -78384,6 +78377,8 @@ USER_COMMANDS_WITH_OBJECTS = {
|
||||
Cmd.ARG_USERLIST: doPrintUserList,
|
||||
Cmd.ARG_VACATION: printShowVacation,
|
||||
Cmd.ARG_VAULTHOLD: printShowUserVaultHolds,
|
||||
Cmd.ARG_WEBMASTERSITE: printShowWebMasterSites,
|
||||
Cmd.ARG_WEBRESOURCE: printShowWebResources,
|
||||
Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation,
|
||||
Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel,
|
||||
}
|
||||
@@ -78494,6 +78489,8 @@ USER_COMMANDS_WITH_OBJECTS = {
|
||||
Cmd.ARG_TOKEN: printShowTokens,
|
||||
Cmd.ARG_VAULTHOLD: printShowUserVaultHolds,
|
||||
Cmd.ARG_VACATION: printShowVacation,
|
||||
Cmd.ARG_WEBMASTERSITE: printShowWebMasterSites,
|
||||
Cmd.ARG_WEBRESOURCE: printShowWebResources,
|
||||
Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation,
|
||||
Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel,
|
||||
}
|
||||
@@ -78745,6 +78742,8 @@ USER_COMMANDS_OBJ_ALIASES = {
|
||||
Cmd.ARG_USERS: Cmd.ARG_USER,
|
||||
Cmd.ARG_VAULTHOLDS: Cmd.ARG_VAULTHOLD,
|
||||
Cmd.ARG_VERIFICATIONCODES: Cmd.ARG_BACKUPCODE,
|
||||
Cmd.ARG_WEBMASTERSITES: Cmd.ARG_WEBMASTERSITE,
|
||||
Cmd.ARG_WEBRESOURCES: Cmd.ARG_WEBRESOURCE,
|
||||
Cmd.ARG_WORKINGLOCATIONS: Cmd.ARG_WORKINGLOCATION,
|
||||
Cmd.ARG_YOUTUBECHANNELS: Cmd.ARG_YOUTUBECHANNEL,
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ PRINTERS = 'printers'
|
||||
PUBSUB = 'pubsub'
|
||||
REPORTS = 'reports'
|
||||
RESELLER = 'reseller'
|
||||
SEARCHCONSOLE = 'searchconsole'
|
||||
SERVICEACCOUNTLOOKUP = 'serviceaccountlookup'
|
||||
SERVICEMANAGEMENT = 'servicemanagement'
|
||||
SERVICEUSAGE = 'serviceusage'
|
||||
@@ -198,6 +199,7 @@ PROJECT_APIS = [
|
||||
'people.googleapis.com',
|
||||
'pubsub.googleapis.com',
|
||||
'reseller.googleapis.com',
|
||||
'searchconsole.googleapis.com',
|
||||
'sheets.googleapis.com',
|
||||
'siteverification.googleapis.com',
|
||||
'storage-api.googleapis.com',
|
||||
@@ -271,6 +273,7 @@ _INFO = {
|
||||
PUBSUB: {'name': 'Pub / Sub API', 'version': 'v1', 'v2discovery': True},
|
||||
REPORTS: {'name': 'Reports API', 'version': 'reports_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
|
||||
RESELLER: {'name': 'Reseller API', 'version': 'v1', 'v2discovery': True},
|
||||
SEARCHCONSOLE: {'name': 'Search Console API', 'version': 'v1', 'v2discovery': True},
|
||||
SERVICEACCOUNTLOOKUP: {'name': 'Service Account Lookup pseudo-API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
|
||||
SERVICEMANAGEMENT: {'name': 'Service Management API', 'version': 'v1', 'v2discovery': True},
|
||||
SERVICEUSAGE: {'name': 'Service Usage API', 'version': 'v1', 'v2discovery': True},
|
||||
@@ -697,10 +700,20 @@ _SVCACCT_SCOPES = [
|
||||
'api': PEOPLE_OTHERCONTACTS,
|
||||
'subscopes': [],
|
||||
'scope': 'https://www.googleapis.com/auth/contacts.other.readonly'},
|
||||
{'name': 'Search Console API - read only',
|
||||
'api': SEARCHCONSOLE,
|
||||
'subscopes': [],
|
||||
'offByDefault': True,
|
||||
'scope': 'https://www.googleapis.com/auth/webmasters.readonly'},
|
||||
{'name': 'Sheets API',
|
||||
'api': SHEETS,
|
||||
'subscopes': READONLY,
|
||||
'scope': 'https://www.googleapis.com/auth/spreadsheets'},
|
||||
{'name': 'Site Verification API',
|
||||
'api': SITEVERIFICATION,
|
||||
'subscopes': [],
|
||||
'offByDefault': True,
|
||||
'scope': 'https://www.googleapis.com/auth/siteverification'},
|
||||
{'name': 'Tag Manager API - Accounts, Containers, Workspaces, Tags - read only',
|
||||
'api': TAGMANAGER,
|
||||
'subscopes': [],
|
||||
@@ -750,56 +763,6 @@ _USER_SVCACCT_ONLY_SCOPES = [
|
||||
'scope': 'https://www.googleapis.com/auth/apps.groups.migration'},
|
||||
]
|
||||
|
||||
DRIVE3_TO_DRIVE2_ABOUT_FIELDS_MAP = {
|
||||
'displayName': 'name',
|
||||
'limit': 'quotaBytesTotal',
|
||||
'usage': 'quotaBytesUsedAggregate',
|
||||
'usageInDrive': 'quotaBytesUsed',
|
||||
'usageInDriveTrash': 'quotaBytesUsedInTrash',
|
||||
}
|
||||
|
||||
DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP = {
|
||||
'canComment': 'canComment',
|
||||
'canReadRevisions': 'canReadRevisions',
|
||||
'canCopy': 'copyable',
|
||||
'canEdit': 'editable',
|
||||
'canShare': 'shareable',
|
||||
}
|
||||
|
||||
DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP = {
|
||||
'canChangeViewersCanCopyContent': 'canChangeRestrictedDownload',
|
||||
}
|
||||
|
||||
DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP = {
|
||||
'allowFileDiscovery': 'withLink',
|
||||
'createdTime': 'createdDate',
|
||||
'expirationTime': 'expirationDate',
|
||||
'modifiedByMe': 'modified',
|
||||
'modifiedByMeTime': 'modifiedByMeDate',
|
||||
'modifiedTime': 'modifiedDate',
|
||||
'name': 'title',
|
||||
'restrictionTime': 'restrictionDate',
|
||||
'sharedWithMeTime': 'sharedWithMeDate',
|
||||
'size': 'fileSize',
|
||||
'trashedTime': 'trashedDate',
|
||||
'viewedByMe': 'viewed',
|
||||
'viewedByMeTime': 'lastViewedByMeDate',
|
||||
'webViewLink': 'alternateLink',
|
||||
}
|
||||
|
||||
DRIVE3_TO_DRIVE2_LABELS_MAP = {
|
||||
'modifiedByMe': 'modified',
|
||||
'starred': 'starred',
|
||||
'trashed': 'trashed',
|
||||
'viewedByMe': 'viewed',
|
||||
}
|
||||
|
||||
DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP = {
|
||||
'modifiedTime': 'modifiedDate',
|
||||
'keepForever': 'pinned',
|
||||
'size': 'fileSize',
|
||||
}
|
||||
|
||||
def getAPIName(api):
|
||||
return _INFO[api]['name']
|
||||
|
||||
|
||||
@@ -155,8 +155,6 @@ DRIVE_DIR = 'drive_dir'
|
||||
DRIVE_MAX_RESULTS = 'drive_max_results'
|
||||
# Use Drive V3 beta
|
||||
DRIVE_V3_BETA = 'drive_v3_beta'
|
||||
# Use Drive V3 ntive names
|
||||
DRIVE_V3_NATIVE_NAMES = 'drive_v3_native_names'
|
||||
# When processing email messages in batches, how many should be processed in each batch
|
||||
EMAIL_BATCH_SIZE = 'email_batch_size'
|
||||
# Enable Delegated Admin Service Account
|
||||
@@ -382,7 +380,6 @@ Defaults = {
|
||||
ENFORCE_EXPANSIVE_ACCESS: TRUE,
|
||||
DRIVE_MAX_RESULTS: '1000',
|
||||
DRIVE_V3_BETA: FALSE,
|
||||
DRIVE_V3_NATIVE_NAMES: TRUE,
|
||||
EMAIL_BATCH_SIZE: '50',
|
||||
ENABLE_DASA: FALSE,
|
||||
ENABLE_GCLOUD_REAUTH: FALSE,
|
||||
@@ -551,7 +548,6 @@ VAR_INFO = {
|
||||
ENFORCE_EXPANSIVE_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
|
||||
DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
|
||||
DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN},
|
||||
DRIVE_V3_NATIVE_NAMES: {VAR_TYPE: TYPE_BOOLEAN},
|
||||
EMAIL_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
|
||||
ENABLE_DASA: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'enabledasa.txt', VAR_SFFT: (FALSE, TRUE)},
|
||||
ENABLE_GCLOUD_REAUTH: {VAR_TYPE: TYPE_BOOLEAN},
|
||||
|
||||
@@ -830,6 +830,10 @@ class GamCLArgs():
|
||||
ARG_VERIFICATION = 'verification'
|
||||
ARG_VERIFICATIONCODES = 'verificationcodes'
|
||||
ARG_VERIFY = 'verify'
|
||||
ARG_WEBMASTERSITE = 'webmastersite'
|
||||
ARG_WEBMASTERSITES = 'webmastersites'
|
||||
ARG_WEBRESOURCE = 'webresource'
|
||||
ARG_WEBRESOURCES = 'webresources'
|
||||
ARG_WORKINGLOCATION = 'workinglocation'
|
||||
ARG_WORKINGLOCATIONS = 'workinglocations'
|
||||
ARG_YOUTUBECHANNEL = 'youtubechannel'
|
||||
|
||||
@@ -394,6 +394,8 @@ class GamEntity():
|
||||
VAULT_MATTER_ID = 'vlmi'
|
||||
VAULT_OPERATION = 'vlto'
|
||||
VAULT_QUERY = 'vltq'
|
||||
WEB_MASTERSITE = 'wems'
|
||||
WEB_RESOURCE = 'were'
|
||||
WEBCLIPS_ENABLED = 'webc'
|
||||
YOUTUBE_CHANNEL = 'ytch'
|
||||
# _NAMES[0] is plural, _NAMES[1] is singular unless the item name is explicitly plural (Calendar Settings)
|
||||
@@ -752,6 +754,8 @@ class GamEntity():
|
||||
VAULT_OPERATION: ['Vault Operations', 'Vault Operation'],
|
||||
VAULT_QUERY: ['Vault Queries', 'Vault Query'],
|
||||
WEBCLIPS_ENABLED: ['Web Clips Enabled', 'Web Clips Enabled'],
|
||||
WEB_MASTERSITE: ['Web Master Sites', 'Web Master Site'],
|
||||
WEB_RESOURCE: ['Web Resources', 'Web Resource'],
|
||||
YOUTUBE_CHANNEL: ['YouTube Channels', 'YouTube Channel'],
|
||||
ROLE_MANAGER: ['Managers', 'Manager'],
|
||||
ROLE_MEMBER: ['Members', 'Member'],
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
!All Google Drive API calls have been converted from v2 to v3, see: https://developers.google.com/drive/v3/web/migration
|
||||
Many of the changes are internal to Gam and have no visible effect. Google has modified/renamed many field names and these will affect scripts that parse the output from `gam print/show drivesettings/drivefileacls/fileinfo/filelist/filerevisions`. Additionally, Google has dropped some fields and their values are no longer available. On input, Gam accepts both the old and new field names.
|
||||
Legacy GAM used Drive API v2, GAM7 uses Drive API v3. See: https://developers.google.com/drive/v3/web/migration
|
||||
Many of the changes are internal to GAM7 and have no visible effect.
|
||||
Google has modified/renamed many field names and these will affect scripts that parse the output from `gam print/show drivesettings/drivefileacls/fileinfo/filelist/filerevisions`.
|
||||
Additionally, Google has dropped some fields and their values are no longer available. On input, GAM7 accepts both the old and new field names where applicable.
|
||||
|
||||
A variable, `drive_v3_native_names` (default value is True), has been added to `gam.cfg` to control the field names on output: when True, the v3 native field names are used; when False, the v3 native field names are mapped to the v2 field names.
|
||||
|
||||
If you have scripts that process the output from these print commands, you may have to make modifications to your scripts.
|
||||
Run your print/show commands with a version of Legacy Gam and save the output.
|
||||
With drive_v3_native_names = False, run your print/show commands with this version of Gam and compare the output to that saved in the previous run;
|
||||
If you use Legacy GAM and have scripts that process the output from these print commands, you may have to make modifications to your scripts when you upgrade to GAM7.
|
||||
Run your print/show commands with a version of Legacy GAM and save the output.
|
||||
Run your print/show commands with GAM7 and compare the output to that saved in the previous run;
|
||||
modify your scripts that process the output as appropriate.
|
||||
|
||||
There is a cost to mapping the v3 field names back to the v2 field names; you can avoid this cost by setting drive_v3_native_names = True,
|
||||
running your print/show commands, comparing the output and making the appropriate script modifications.
|
||||
```
|
||||
print/show drivesettings
|
||||
Dropped fields:
|
||||
@@ -30,7 +28,7 @@ Dropped fields:
|
||||
authKey
|
||||
Renamed fields (Old->New):
|
||||
name->displayName
|
||||
withLink->allowFileDiscovery
|
||||
withLink->allowFileDiscovery - value is complemented
|
||||
|
||||
print/show fileinfo/filelist
|
||||
Dropped fields:
|
||||
@@ -40,19 +38,20 @@ Dropped fields:
|
||||
labels(hidden)
|
||||
markedViewedByMeDate
|
||||
openWithLinks
|
||||
selfLink
|
||||
ownerNames
|
||||
parents(isRoot)
|
||||
parents(parentLink)
|
||||
parents(selfLink)
|
||||
permissions(selfLink)
|
||||
selfLink
|
||||
userPermission(selfLink)
|
||||
userPermission
|
||||
Renamed fields (Old->New):
|
||||
alternateLink->webViewLink
|
||||
capabilities(canChangeRestrictedDownload)->capabilities(canChangeViewersCanCopyContent)
|
||||
createdDate->createdTime
|
||||
expirationDate->expirationTime
|
||||
fileSize->size
|
||||
lastModifyingUserName->lastModifyingUser(displayName)
|
||||
lastViewedByMeDate->viewedByMeTime
|
||||
modified->modifiedByMe
|
||||
modifiedByMeDate->modifiedByMeTime
|
||||
@@ -76,18 +75,3 @@ Renamed fields (Old->New):
|
||||
picture.url->photoLink
|
||||
pinned->keepForever
|
||||
```
|
||||
The parents field of a file has undergone the most change. In Drive v2 it was a list of compound items with three sub-fields per item: id, isRoot, parentLink.
|
||||
In Drive v3 the parents field is a list of simple items, the parent ids. The following examples show how the parents field is output in a CSV file for a file with two parents.
|
||||
```
|
||||
Previous versions of Gam:
|
||||
Owner,title,parents,parents.0.isRoot,parents.0.id,parents.0.parentLink,parents.1.isRoot,parents.1.id,parents.1.parentLink
|
||||
testuser@domain.com,TestFile,2,True,PPPP1111,https://www.googleapis.com/drive/v2/files/PPPP1111,False,PPPP2222,https://www.googleapis.com/drive/v2/files/PPPP2222
|
||||
|
||||
Current version of Gam with drive_v3_name_names = false
|
||||
Owner,title,parents,parents.0.id,parents.1.id
|
||||
testuser@domain.com,TestFile,2,PPPP1111,PPPP2222
|
||||
|
||||
Current version of Gam with drive_v3_name_names = true
|
||||
Owner,name,parents
|
||||
testuser@domain.com,TestFile,PPPP1111 PPPP2222
|
||||
```
|
||||
|
||||
@@ -10,6 +10,73 @@ 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.17.02
|
||||
|
||||
Updated `gam <UserTypeEntity> print|show webmastersites` to handle the following error
|
||||
that occurs if you haven't updated your project to include the Google Search Console API.
|
||||
```
|
||||
ERROR: 403: permissionDenied - Google Search Console API has not been used in project 111055363999 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/searchconsole.googleapis.com/overview?project=111055363999 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
|
||||
```
|
||||
|
||||
### 7.17.01
|
||||
|
||||
Fixed bug in `gam <UserTypeEntity> show webmastersites` that caused a trap.
|
||||
|
||||
### 7.17.00
|
||||
|
||||
Added commands to discover Sites and WebResources that managed users (previously unmanaged) may have access to for better governance and visibility.
|
||||
These are special purpose commands and will not generally be used.
|
||||
```
|
||||
gam <UserTypeEntity> show webresources
|
||||
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
|
||||
gam <UserTypeEntity> show webmastersites
|
||||
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
|
||||
```
|
||||
|
||||
### 7.16.01
|
||||
|
||||
The Drive API now supports setting download restrictions on individual files.
|
||||
|
||||
Added `downloadrestictions` and `<DriveDownloadRestrictionsSubfieldName>` to `<DriveFieldName>`.
|
||||
```
|
||||
<DriveDownloadRestrictionsSubfieldName> ::=
|
||||
downloadrestrictions.itemdownloadrestriction|
|
||||
downloadrestrictions.effectivedownloadrestrictionwithcontext
|
||||
```
|
||||
|
||||
Added `itemdownloadrestriction (restrictedforreaders [<Boolean>]) (restrictedforwriters [<Boolean>])`
|
||||
to `<DriveFileAttribute>`.
|
||||
|
||||
From the Drive API documentation:
|
||||
```
|
||||
itemDownloadRestriction - The download restriction of the file applied directly by the owner or organizer. This does not take into account shared drive settings or DLP rules.
|
||||
effectiveDownloadRestrictionWithContext - Output only. The effective download restriction applied to this file. This considers all restriction settings and DLP rules.
|
||||
restrictedForReaders - Whether download and copy is restricted for readers.
|
||||
restrictedForWriters - Whether download and copy is restricted for writers. If true, download is also restricted for readers.
|
||||
```
|
||||
|
||||
### 7.16.00
|
||||
|
||||
Removed `drive_v3_native_names` from `gam.cfg`; GAM now only uses Drive API v3 fields names on output.
|
||||
If you had `drive_v3_native_names = False` in `gam.cfg` or are updating from Legacy GAM:
|
||||
|
||||
* See: https://github.com/GAM-team/GAM/wiki/Drive-REST-API-v3
|
||||
|
||||
### 7.15.01
|
||||
|
||||
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
|
||||
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
|
||||
and `downloadrestrictedforwriters` were supported (they are still supported).
|
||||
|
||||
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
|
||||
|
||||
### 7.15.00
|
||||
|
||||
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`
|
||||
as documented; it was defaulting to `False`.
|
||||
|
||||
Cleaned up code for processing Python dictionary structures; this should have no noticable effect.
|
||||
|
||||
### 7.14.04
|
||||
|
||||
Fixed bug in `gam print|show cigroups cimember <UserItem>` that generated the following error:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
|
||||
and all necessary authentications.
|
||||
|
||||
- [Drive API v2 to Drive API v3](Drive-REST-v3)
|
||||
- [Downloads-Installs](Downloads-Installs)
|
||||
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
|
||||
- [Windows](#windows)
|
||||
@@ -251,7 +252,7 @@ writes the credentials into the file oauth2.txt.
|
||||
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||
admin@server:/Users/admin$ gam version
|
||||
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
MacOS Sequoia 15.5 x86_64
|
||||
@@ -989,7 +990,7 @@ writes the credentials into the file oauth2.txt.
|
||||
C:\>del C:\GAMConfig\oauth2.txt
|
||||
C:\>gam version
|
||||
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
||||
GAM 7.14.04 - https://github.com/GAM-team/GAM - pythonsource
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM - pythonsource
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
Windows-10-10.0.17134 AMD64
|
||||
|
||||
@@ -203,8 +203,8 @@
|
||||
allowcontentmanagerstosharefolders|
|
||||
copyrequireswriterpermission|
|
||||
domainusersonly|
|
||||
downloadrestrictedforreaders|
|
||||
downloadrestrictedforwriters|
|
||||
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
|
||||
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
|
||||
drivemembersonly|teammembersonly|
|
||||
sharingfoldersrequiresorganizerpermission
|
||||
|
||||
@@ -247,7 +247,7 @@ The user that creates a Shared Drive is given the permission role organizer for
|
||||
gam [<UserTypeEntity>] create shareddrive <Name>
|
||||
[(theme|themeid <String>)|
|
||||
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
|
||||
@@ -259,7 +259,7 @@ gam [<UserTypeEntity>] create shareddrive <Name>
|
||||
* `<Float>` - Y coordinate, typically 0.0
|
||||
* `<Float>` - width, typically 1.0
|
||||
* `color` - set the Shared Drive color
|
||||
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `hide <Boolean>` - Set Shared Drive visibility
|
||||
|
||||
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
|
||||
@@ -333,13 +333,13 @@ gam [<UserTypeEntity>] update shareddrive <SharedDriveEntity> [name <Name>]
|
||||
[adminaccess|asadmin]
|
||||
[(theme|themeid <String>)|
|
||||
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
```
|
||||
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
|
||||
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
|
||||
* `color` - set the Shared Drive color
|
||||
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `hidden <Boolean>` - Set Shared Drive visibility
|
||||
|
||||
* `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html
|
||||
|
||||
@@ -157,12 +157,16 @@
|
||||
contentrestrictions.restrictiontime|
|
||||
contentrestrictions.type
|
||||
|
||||
<DriveLabelInfoSubfieldName> ::=
|
||||
<DriveDownloadRestrictionsSubfieldName> ::=
|
||||
downloadrestrictions.itemdownloadrestriction|
|
||||
downloadrestrictions.effectivedownloadrestrictionwithcontext
|
||||
|
||||
<ClassificationLabelInfoSubfieldName> ::=
|
||||
labels.id| # modifiedByMe
|
||||
labels.revisionid| # copyRequiresWriterPermission
|
||||
labels.fields # viewedByMe
|
||||
|
||||
<DriveLabelsSubfieldName> ::=
|
||||
<ClassificationLabelsSubfieldName~> ::=
|
||||
labels.modified| # modifiedByMe
|
||||
labels.restricted| # copyRequiresWriterPermission
|
||||
labels.starred| # starred
|
||||
@@ -251,6 +255,8 @@
|
||||
copyrequireswriterpermission|
|
||||
createddate|createdtime|
|
||||
description|
|
||||
downloadrestictions|
|
||||
<DriveDownloadRestrictionsSubfieldName>|
|
||||
driveid|
|
||||
drivename|
|
||||
editable|
|
||||
@@ -269,9 +275,9 @@
|
||||
inheritedpermissionsdisabled|
|
||||
isappauthorized|
|
||||
labelinfo|
|
||||
<DriveLabelInfoSubfieldName>|
|
||||
<ClassificationLabelInfoSubfieldName>|
|
||||
labels|
|
||||
<DriveLabelsSubfieldName>|
|
||||
<ClassificationLabelsSubfieldName>|
|
||||
lastmodifyinguser|
|
||||
<DriveLastModifyingUserSubfieldName>|
|
||||
lastmodifyingusername|
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
(folderColorRgb <ColorValue>)|
|
||||
(indexabletext <String>)|
|
||||
(inheritedpermissionsdisabled [<Boolean>])|
|
||||
(itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>])|
|
||||
(keeprevisionforever|pinned)|
|
||||
(lastviewedbyme <Time>)|
|
||||
(mimetype <MimeType>)|
|
||||
|
||||
@@ -181,8 +181,8 @@
|
||||
allowcontentmanagerstosharefolders|
|
||||
copyrequireswriterpermission|
|
||||
domainusersonly|
|
||||
downloadrestrictedforreaders|
|
||||
downloadrestrictedforwriters|
|
||||
downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
|
||||
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
|
||||
drivemembersonly|teammembersonly|
|
||||
sharingfoldersrequiresorganizerpermission
|
||||
|
||||
@@ -217,7 +217,7 @@ The user that creates a Shared Drive is given the permission role organizer for
|
||||
gam <UserTypeEntity> create shareddrive <Name>
|
||||
[(theme|themeid <String>)|
|
||||
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
|
||||
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
|
||||
@@ -228,7 +228,7 @@ gam <UserTypeEntity> create shareddrive <Name>
|
||||
* `<Float>` - Y coordinate, typically 0.0
|
||||
* `<Float>` - width, typically 1.0
|
||||
* `color` - set the Shared Drive color
|
||||
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `hide <Boolean>` - Set Shared Drive visibility
|
||||
|
||||
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
|
||||
@@ -284,13 +284,13 @@ This command is used to set basic Shared Drive settings.
|
||||
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [adminaccess|asadmin] [name <Name>]
|
||||
[(theme|themeid <String>)|
|
||||
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
|
||||
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
|
||||
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
|
||||
```
|
||||
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
|
||||
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
|
||||
* `color` - set the Shared Drive color
|
||||
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
|
||||
* `hidden <Boolean>` - Set Shared Drive visibility
|
||||
|
||||
This option is only available when the command is run as an administrator.
|
||||
|
||||
48
wiki/Users-Web-Resources-and-Sites.md
Normal file
48
wiki/Users-Web-Resources-and-Sites.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Users - Web Resources and Sites
|
||||
- [API documentation](#api-documentation)
|
||||
- [Introduction](#introduction)
|
||||
- [Definitions](#definitions)
|
||||
- [Display Web Resources](#display-web-resources)
|
||||
- [Display Web Sites](#display-web-sites)
|
||||
|
||||
## API documentation
|
||||
* [Web Resources](https://developers.google.com/site-verification/v1/webResource/list)
|
||||
* [Web Sites](https://developers.google.com/webmaster-tools/v1/sites/list)
|
||||
|
||||
|
||||
## Introduction
|
||||
These features were added in version 7.17.00.
|
||||
|
||||
To use these commands you add the 'Search Console API' to your project and update your service account authorization.
|
||||
```
|
||||
gam update project
|
||||
gam user user@domain.com update serviceaccount
|
||||
...
|
||||
[*] 39) Search Console API - read only
|
||||
[*] 42) Site Verification API
|
||||
|
||||
```
|
||||
## Definitions
|
||||
* [`<UserTypeEntity>`](Collections-of-Users)
|
||||
|
||||
## Display Web Resources
|
||||
```
|
||||
gam <UserItem> show webresources
|
||||
```
|
||||
Gam displays the information as an indented list of keys and values.
|
||||
|
||||
```
|
||||
gam <UserItem> print webresources [todrive <ToDriveAttribute>*]
|
||||
```
|
||||
Gam displays the information as columns of fields.
|
||||
|
||||
## Display Web Sites
|
||||
```
|
||||
gam <UserItem> show websites
|
||||
```
|
||||
Gam displays the information as an indented list of keys and values.
|
||||
|
||||
```
|
||||
gam <UserItem> print websites [todrive <ToDriveAttribute>*]
|
||||
```
|
||||
Gam displays the information as columns of fields.
|
||||
@@ -1,10 +1,9 @@
|
||||
k
|
||||
# Version and Help
|
||||
|
||||
Print the current version of Gam with details
|
||||
```
|
||||
gam version
|
||||
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
MacOS Sequoia 15.5 x86_64
|
||||
@@ -16,7 +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.14.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
MacOS Sequoia 15.5 x86_64
|
||||
@@ -28,7 +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.14.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
MacOS Sequoia 15.5 x86_64
|
||||
@@ -65,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Version Check:
|
||||
Current: 5.35.08
|
||||
Latest: 7.14.04
|
||||
Latest: 7.17.02
|
||||
echo $?
|
||||
1
|
||||
```
|
||||
@@ -73,7 +72,7 @@ echo $?
|
||||
Print the current version number without details
|
||||
```
|
||||
gam version simple
|
||||
7.14.04
|
||||
7.17.02
|
||||
```
|
||||
In Linux/MacOS you can do:
|
||||
```
|
||||
@@ -83,7 +82,7 @@ echo $VER
|
||||
Print the current version of Gam and address of this Wiki
|
||||
```
|
||||
gam help
|
||||
GAM 7.14.04 - https://github.com/GAM-team/GAM
|
||||
GAM 7.17.02 - https://github.com/GAM-team/GAM
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.5 64-bit final
|
||||
MacOS Sequoia 15.5 x86_64
|
||||
|
||||
@@ -174,6 +174,7 @@ Service Account Access
|
||||
* [Users - Tag Manager](Users-Tag-Manager)
|
||||
* [Users - Tasks](Users-Tasks)
|
||||
* [Users - YouTube](Users-YouTube)
|
||||
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites)
|
||||
|
||||
GAM Tutorials
|
||||
* [Account Auditing](l-ExamplesAccountAuditing)
|
||||
|
||||
@@ -412,9 +412,8 @@ never_time
|
||||
has the value "1970-01-01T00:00:00.000Z"
|
||||
Default: Never
|
||||
no_browser
|
||||
If no_browser is True, GAM won't open a browser if todrive is set
|
||||
when creating CSV files and GAM prints a link and waits for
|
||||
the verification code when oauth2.txt is being created
|
||||
If no_browser is True, GAM won't open a browser when it prints a link
|
||||
and waits for the verification code when oauth2.txt is being created/updated
|
||||
Signal file: OldGamPath/nobrowser.txt
|
||||
no_cache
|
||||
Disable GAM API caching
|
||||
|
||||
Reference in New Issue
Block a user