mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 09:51:36 +00:00
Fix group settings (#990)
* Fix group settings Clean up md5MatchesFile * Simplify doGetCustomerInfo Avoid trap when doPrintDomains returned a domain creationTime with no fraction. Traceback (most recent call last): File "gam.py", line 14761, in <module> File "gam.py", line 14159, in ProcessGAMCommand File "gam.py", line 2053, in doGetDomainInfo File "gam.py", line 2088, in doGetCustomerInfo File "_strptime.py", line 577, in _strptime_datetime File "_strptime.py", line 359, in _strptime ValueError: time data '2019-04-23 16:14:56' does not match format '%Y-%m-%d %H:% M:%S.%f' lansa.co.uk,True,2019-04-23 16:14:13.041000,secondary, lansa.com.au,True,2019-04-23 16:14:56,secondary
This commit is contained in:
@@ -874,7 +874,7 @@ gam info resoldsubscriptions <CustomerID> [customer_auth_token <String>]
|
||||
<ReportsAppList> ::= "<ReportsApp>(,<ReportsApp>)*"
|
||||
|
||||
gam report users|user [todrive] [date <Date>] [fulldatarequired all|<ReportsAppList>]
|
||||
[(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath>)] [filter|filters <String>] [fields|parameters <String>]
|
||||
[(user <UserItem>)|(orgunit|org|ou <OrgUnitPath>)] [filter|filters <String>] [fields|parameters <String>]
|
||||
gam report customers|customer|domain [todrive] [date <Date>] [fulldatarequired all|<ReportsAppList>]
|
||||
[fields|parameters <String>]
|
||||
gam report admin|calendar|calendars|drive|docs|doc|groups|group|logins|login|mobile|tokens|token [todrive]
|
||||
|
||||
94
src/gam.py
94
src/gam.py
@@ -2082,13 +2082,14 @@ def doGetCustomerInfo():
|
||||
# If customer has changed primary domain customerCreationTime is date
|
||||
# of current primary being added, not customer create date.
|
||||
# We should also get all domains and use oldest date
|
||||
domains = doPrintDomains(return_results=True)
|
||||
oldest = datetime.datetime.strptime(customer_info['customerCreationTime'], '%Y-%m-%dT%H:%M:%S.%fZ')
|
||||
domains = callGAPIitems(cd.domains(), 'list', 'domains',
|
||||
customer=GC_Values[GC_CUSTOMER_ID], fields='domains(creationTime)')
|
||||
for domain in domains:
|
||||
domain_creation = datetime.datetime.strptime(domain['creationTime'], '%Y-%m-%d %H:%M:%S.%f')
|
||||
domain_creation = datetime.datetime.fromtimestamp(int(domain['creationTime'])/1000)
|
||||
if domain_creation < oldest:
|
||||
oldest = domain_creation
|
||||
print('Customer Creation Time: %s' % oldest)
|
||||
print('Customer Creation Time: %s' % oldest.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
||||
print('Default Language: %s' % customer_info.get('language', 'Unset (defaults to en)'))
|
||||
if 'postalAddress' in customer_info:
|
||||
print('Address:')
|
||||
@@ -2167,7 +2168,7 @@ def doDelDomainAlias():
|
||||
domainAliasName = sys.argv[3]
|
||||
callGAPI(cd.domainAliases(), 'delete', customer=GC_Values[GC_CUSTOMER_ID], domainAliasName=domainAliasName)
|
||||
|
||||
def doPrintDomains(return_results=False):
|
||||
def doPrintDomains():
|
||||
cd = buildGAPIObject('directory')
|
||||
todrive = False
|
||||
titles = ['domainName',]
|
||||
@@ -2208,8 +2209,6 @@ def doPrintDomains(return_results=False):
|
||||
titles.append(attr)
|
||||
aliasdomain_attributes[attr] = aliasdomain[attr]
|
||||
csvRows.append(aliasdomain_attributes)
|
||||
if return_results:
|
||||
return csvRows
|
||||
writeCSVfile(csvRows, titles, 'Domains', todrive)
|
||||
|
||||
def doPrintDomainAliases():
|
||||
@@ -8431,11 +8430,10 @@ def _getCloudStorageObject(s, bucket, object_, local_file=None, expectedMd5=None
|
||||
if expectedMd5:
|
||||
sys.stdout.write('Verifying %s hash...' % expectedMd5)
|
||||
sys.stdout.flush()
|
||||
if md5MatchesFile(local_file, expectedMd5):
|
||||
if md5MatchesFile(local_file, expectedMd5, False):
|
||||
print('VERIFIED')
|
||||
return
|
||||
else:
|
||||
print('not verified. Downloading again and over-writing...')
|
||||
print('not verified. Downloading again and over-writing...')
|
||||
else:
|
||||
return # nothing to verify, just assume we're good.
|
||||
print('saving to %s' % local_file)
|
||||
@@ -8460,19 +8458,18 @@ def _getCloudStorageObject(s, bucket, object_, local_file=None, expectedMd5=None
|
||||
f = openFile(local_file, 'rb')
|
||||
sys.stdout.write(' Verifying file hash is %s...' % expectedMd5)
|
||||
sys.stdout.flush()
|
||||
if md5MatchesFile(local_file, expectedMd5):
|
||||
print('VERIFIED')
|
||||
else:
|
||||
print('ERROR: actual hash was %s. Exiting on corrupt file.' % actual_hash)
|
||||
sys.exit(6)
|
||||
md5MatchesFile(local_file, expectedMd5, True)
|
||||
print('VERIFIED')
|
||||
closeFile(f)
|
||||
|
||||
def md5MatchesFile(local_file, expected_md5):
|
||||
def md5MatchesFile(local_file, expected_md5, exitOnError):
|
||||
f = openFile(local_file, 'rb')
|
||||
hash_md5 = hashlib.md5()
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hash_md5.update(chunk)
|
||||
actual_hash = hash_md5.hexdigest()
|
||||
if exitOnError and actual_hash != expected_md5:
|
||||
systemErrorExit(6, 'actual hash was %s. Exiting on corrupt file.' % actual_hash)
|
||||
return actual_hash == expected_md5
|
||||
|
||||
def doDownloadCloudStorageBucket():
|
||||
@@ -8541,11 +8538,8 @@ def doDownloadVaultExport():
|
||||
expected_hash = s_file['md5Hash']
|
||||
sys.stdout.write(' Verifying file hash is %s...' % expected_hash)
|
||||
sys.stdout.flush()
|
||||
if md5MatchesFile(filename, expected_hash):
|
||||
print('VERIFIED')
|
||||
else:
|
||||
print('ERROR: actual hash was %s. Exiting on corrupt file.' % actual_hash)
|
||||
sys.exit(6)
|
||||
md5MatchesFile(filename, expected_hash, True)
|
||||
print('VERIFIED')
|
||||
if extractFiles and re.search(r'\.zip$', filename):
|
||||
extract_nested_zip(filename, targetFolder)
|
||||
|
||||
@@ -8869,21 +8863,11 @@ def doCreateUser():
|
||||
def GroupIsAbuseOrPostmaster(emailAddr):
|
||||
return emailAddr.startswith('abuse@') or emailAddr.startswith('postmaster@')
|
||||
|
||||
def mapCollaborativeACL(myarg, value):
|
||||
value = value.lower().replace('_', '')
|
||||
if value in COLLABORATIVE_ACL_CHOICES:
|
||||
return COLLABORATIVE_ACL_CHOICES[value]
|
||||
systemErrorExit(3, 'allowed choices for %s are %s, got %s' % (myarg, ', '.join(sorted(COLLABORATIVE_ACL_CHOICES)), value))
|
||||
GROUP_SETTINGS_LIST_PATTERN = re.compile(r'([A-Z][A-Z_]+[A-Z]?):')
|
||||
|
||||
def getGroupAttrValue(myarg, value, gs_object, gs_body, function):
|
||||
if myarg == 'collaborative':
|
||||
value = mapCollaborativeACL(myarg, value)
|
||||
for attrName, attrValue in list(COLLABORATIVE_INBOX_ATTRIBUTES.items()):
|
||||
if attrValue == 'acl':
|
||||
gs_body[attrName] = value
|
||||
else:
|
||||
gs_body[attrName] = attrValue
|
||||
return
|
||||
myarg = 'enablecollaborativeinbox'
|
||||
for (attrib, params) in list(gs_object['schemas']['Groups']['properties'].items()):
|
||||
if attrib in ['kind', 'etag', 'email']:
|
||||
continue
|
||||
@@ -8905,19 +8889,19 @@ def getGroupAttrValue(myarg, value, gs_object, gs_body, function):
|
||||
value = value.replace('\\n', '\n')
|
||||
elif attrib == 'primaryLanguage':
|
||||
value = LANGUAGE_CODES_MAP.get(value.lower(), value)
|
||||
elif COLLABORATIVE_INBOX_ATTRIBUTES.get(attrib) == 'acl':
|
||||
value = mapCollaborativeACL(myarg, value)
|
||||
elif params['description'].find(value.upper()) != -1: # ugly hack because API wants some values uppercased.
|
||||
elif attrib in GROUP_SETTINGS_LIST_ATTRIBUTES:
|
||||
value = value.upper()
|
||||
elif value.lower() in true_values:
|
||||
value = 'true'
|
||||
elif value.lower() in false_values:
|
||||
value = 'false'
|
||||
# Another ugly hack because Groups Settings API doesn't have proper enumerator values set in discovery file.
|
||||
if 'description' in params and params['description'].find('Possible values are: ') != -1:
|
||||
possible_values = params['description'][params['description'].find('Possible values are: ')+21:].split(' ')
|
||||
if value not in possible_values:
|
||||
systemErrorExit(2, 'value for %s must be one of %s. Got %s.' % (attrib, ', '.join(possible_values), value))
|
||||
possible_values = GROUP_SETTINGS_LIST_PATTERN.findall(params['description'])
|
||||
if value not in possible_values:
|
||||
systemErrorExit(2, 'value for %s must be one of %s. Got %s.' % (attrib, ', '.join(possible_values), value))
|
||||
elif attrib in GROUP_SETTINGS_BOOLEAN_ATTRIBUTES:
|
||||
value = value.lower()
|
||||
if value in true_values:
|
||||
value = 'true'
|
||||
elif value in false_values:
|
||||
value = 'false'
|
||||
else:
|
||||
systemErrorExit(2, 'value for %s must be true|false. Got %s.' % (attrib, value))
|
||||
gs_body[attrib] = value
|
||||
return
|
||||
systemErrorExit(2, '%s is not a valid argument for "gam %s group"' % (myarg, function))
|
||||
@@ -9697,7 +9681,7 @@ def doUpdateMobile():
|
||||
doit = False
|
||||
if resourceIds[:6] == 'query:':
|
||||
query = resourceIds[6:]
|
||||
fields='nextPageToken,mobiledevices(resourceId,email)'
|
||||
fields = 'nextPageToken,mobiledevices(resourceId,email)'
|
||||
page_message = 'Got %%total_items%% mobile devices...\n'
|
||||
devices = callGAPIpages(cd.mobiledevices(), 'list', page_message=page_message, customerId=GC_Values[GC_CUSTOMER_ID], items='mobiledevices', query=query, fields=fields)
|
||||
else:
|
||||
@@ -11639,11 +11623,14 @@ GROUP_ARGUMENT_TO_PROPERTY_TITLE_MAP = {
|
||||
|
||||
GROUP_ATTRIBUTES_ARGUMENT_TO_PROPERTY_MAP = {
|
||||
'allowexternalmembers': 'allowExternalMembers',
|
||||
'allowgooglecommunication': 'allowGoogleCommunication',
|
||||
'allowwebposting': 'allowWebPosting',
|
||||
'archiveonly': 'archiveOnly',
|
||||
'customfootertext': 'customFooterText',
|
||||
'customreplyto': 'customReplyTo',
|
||||
'defaultmessagedenynotificationtext': 'defaultMessageDenyNotificationText',
|
||||
'enablecollaborativeinbox': 'enableCollaborativeInbox',
|
||||
'favoriterepliesontop': 'favoriteRepliesOnTop',
|
||||
'gal': 'includeInGlobalAddressList',
|
||||
'includecustomfooter': 'includeCustomFooter',
|
||||
'includeinglobaladdresslist': 'includeInGlobalAddressList',
|
||||
@@ -11656,16 +11643,33 @@ GROUP_ATTRIBUTES_ARGUMENT_TO_PROPERTY_MAP = {
|
||||
'showingroupdirectory': 'showInGroupDirectory',
|
||||
'spammoderationlevel': 'spamModerationLevel',
|
||||
'whocanadd': 'whoCanAdd',
|
||||
'whocanapprovemembers': 'whoCanApproveMembers',
|
||||
'whocanapprovemessages': 'whoCanApproveMessages',
|
||||
'whocanassigntopics': 'whoCanAssignTopics',
|
||||
'whocanassistcontent': 'whoCanAssistContent',
|
||||
'whocanbanusers': 'whoCanBanUsers',
|
||||
'whocancontactowner': 'whoCanContactOwner',
|
||||
'whocandeleteanypost': 'whoCanDeleteAnyPost',
|
||||
'whocandeletetopics': 'whoCanDeleteTopics',
|
||||
'whocandiscovergroup': 'whoCanDiscoverGroup',
|
||||
'whocanenterfreeformtags': 'whoCanEnterFreeFormTags',
|
||||
'whocanhideabuse': 'whoCanHideAbuse',
|
||||
'whocaninvite': 'whoCanInvite',
|
||||
'whocanjoin': 'whoCanJoin',
|
||||
'whocanleavegroup': 'whoCanLeaveGroup',
|
||||
'whocanlocktopics': 'whoCanLockTopics',
|
||||
'whocanmaketopicssticky': 'whoCanMakeTopicsSticky',
|
||||
'whocanmarkduplicate': 'whoCanMarkDuplicate',
|
||||
'whocanmarkfavoritereplyonanytopic': 'whoCanMarkFavoriteReplyOnAnyTopic',
|
||||
'whocanmarkfavoritereplyonowntopic': 'whoCanMarkFavoriteReplyOnOwnTopic',
|
||||
'whocanmarknoresponseneeded': 'whoCanMarkNoResponseNeeded',
|
||||
'whocanmoderatecontent': 'whoCanModerateContent',
|
||||
'whocanmoderatemembers': 'whoCanModerateMembers',
|
||||
'whocanmodifymembers': 'whoCanModifyMembers',
|
||||
'whocanmodifytagsandcategories': 'whoCanModifyTagsAndCategories',
|
||||
'whocanmovetopicsin': 'whoCanMoveTopicsIn',
|
||||
'whocanmovetopicsout': 'whoCanMoveTopicsOut',
|
||||
'whocanpostannouncements': 'whoCanPostAnnouncements',
|
||||
'whocanpostmessage': 'whoCanPostMessage',
|
||||
'whocantaketopics': 'whoCanTakeTopics',
|
||||
'whocanunassigntopic': 'whoCanUnassignTopic',
|
||||
|
||||
114
src/var.py
114
src/var.py
@@ -11,10 +11,10 @@ gam_license = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
GAM_URL = 'https://git.io/gam'
|
||||
GAM_INFO = 'GAM {0} - {1} / {2} / Python {3}.{4}.{5} {6} / {7} {8} /'.format(gam_version, GAM_URL,
|
||||
gam_author,
|
||||
sys.version_info[0], sys.version_info[1],
|
||||
sys.version_info[2], sys.version_info[3],
|
||||
platform.platform(), platform.machine())
|
||||
gam_author,
|
||||
sys.version_info[0], sys.version_info[1],
|
||||
sys.version_info[2], sys.version_info[3],
|
||||
platform.platform(), platform.machine())
|
||||
|
||||
GAM_RELEASES = 'https://github.com/jay0lee/GAM/releases'
|
||||
GAM_WIKI = 'https://github.com/jay0lee/GAM/wiki'
|
||||
@@ -157,13 +157,13 @@ API_VER_MAPPING = {
|
||||
API_SCOPE_MAPPING = {
|
||||
'alertcenter': ['https://www.googleapis.com/auth/apps.alerts',],
|
||||
'appsactivity': ['https://www.googleapis.com/auth/activity',
|
||||
'https://www.googleapis.com/auth/drive',],
|
||||
'https://www.googleapis.com/auth/drive',],
|
||||
'calendar': ['https://www.googleapis.com/auth/calendar',],
|
||||
'drive': ['https://www.googleapis.com/auth/drive',],
|
||||
'drive3': ['https://www.googleapis.com/auth/drive',],
|
||||
'gmail': ['https://mail.google.com/',
|
||||
'https://www.googleapis.com/auth/gmail.settings.basic',
|
||||
'https://www.googleapis.com/auth/gmail.settings.sharing',],
|
||||
'https://www.googleapis.com/auth/gmail.settings.basic',
|
||||
'https://www.googleapis.com/auth/gmail.settings.sharing',],
|
||||
'sheets': ['https://www.googleapis.com/auth/spreadsheets',],
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ DOCUMENT_FORMATS_MAP = {
|
||||
'mht': [{'mime': 'message/rfc822', 'ext': 'mht'}],
|
||||
'odp': [{'mime': 'application/vnd.oasis.opendocument.presentation', 'ext': '.odp'}],
|
||||
'ods': [{'mime': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||
{'mime': 'application/vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'}],
|
||||
{'mime': 'application/vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'}],
|
||||
'odt': [{'mime': 'application/vnd.oasis.opendocument.text', 'ext': '.odt'}],
|
||||
'pdf': [{'mime': 'application/pdf', 'ext': '.pdf'}],
|
||||
'png': [{'mime': 'image/png', 'ext': '.png'}],
|
||||
@@ -414,7 +414,7 @@ DOCUMENT_FORMATS_MAP = {
|
||||
'rtf': [{'mime': 'application/rtf', 'ext': '.rtf'}],
|
||||
'svg': [{'mime': 'image/svg+xml', 'ext': '.svg'}],
|
||||
'tsv': [{'mime': 'text/tab-separated-values', 'ext': '.tsv'},
|
||||
{'mime': 'text/tsv', 'ext': '.tsv'}],
|
||||
{'mime': 'text/tsv', 'ext': '.tsv'}],
|
||||
'txt': [{'mime': 'text/plain', 'ext': '.txt'}],
|
||||
'xls': [{'mime': 'application/vnd.ms-excel', 'ext': '.xls'}],
|
||||
'xlt': [{'mime': 'application/vnd.ms-excel', 'ext': '.xlt'}],
|
||||
@@ -425,9 +425,9 @@ DOCUMENT_FORMATS_MAP = {
|
||||
'microsoft': _MICROSOFT_FORMATS_LIST,
|
||||
'micro$oft': _MICROSOFT_FORMATS_LIST,
|
||||
'openoffice': [{'mime': 'application/vnd.oasis.opendocument.presentation', 'ext': '.odp'},
|
||||
{'mime': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||
{'mime': 'application/vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||
{'mime': 'application/vnd.oasis.opendocument.text', 'ext': '.odt'}],
|
||||
{'mime': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||
{'mime': 'application/vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||
{'mime': 'application/vnd.oasis.opendocument.text', 'ext': '.odt'}],
|
||||
}
|
||||
|
||||
DNS_ERROR_CODES_MAP = {
|
||||
@@ -612,28 +612,76 @@ CROS_END_ARGUMENTS = ['end', 'enddate']
|
||||
CROS_TPM_VULN_VERSIONS = ['41f', '420', '628', '8520',]
|
||||
CROS_TPM_FIXED_VERSIONS = ['422', '62b', '8521',]
|
||||
|
||||
COLLABORATIVE_ACL_CHOICES = {
|
||||
'members': 'ALL_MEMBERS',
|
||||
'managersonly': 'MANAGERS_ONLY',
|
||||
'managers': 'OWNERS_AND_MANAGERS',
|
||||
'owners': 'OWNERS_ONLY',
|
||||
'none': 'NONE',
|
||||
}
|
||||
COLLABORATIVE_INBOX_ATTRIBUTES = [
|
||||
'whoCanAddReferences',
|
||||
'whoCanAssignTopics',
|
||||
'whoCanEnterFreeFormTags',
|
||||
'whoCanMarkDuplicate',
|
||||
'whoCanMarkFavoriteReplyOnAnyTopic',
|
||||
'whoCanMarkFavoriteReplyOnOwnTopic',
|
||||
'whoCanMarkNoResponseNeeded',
|
||||
'whoCanModifyTagsAndCategories',
|
||||
'whoCanTakeTopics',
|
||||
'whoCanUnassignTopic',
|
||||
'whoCanUnmarkFavoriteReplyOnAnyTopic',
|
||||
'favoriteRepliesOnTop',
|
||||
]
|
||||
|
||||
COLLABORATIVE_INBOX_ATTRIBUTES = {
|
||||
'whoCanAddReferences': 'acl',
|
||||
'whoCanAssignTopics': 'acl',
|
||||
'whoCanEnterFreeFormTags': 'acl',
|
||||
'whoCanMarkDuplicate': 'acl',
|
||||
'whoCanMarkFavoriteReplyOnAnyTopic': 'acl',
|
||||
'whoCanMarkFavoriteReplyOnOwnTopic': 'acl',
|
||||
'whoCanMarkNoResponseNeeded': 'acl',
|
||||
'whoCanModifyTagsAndCategories': 'acl',
|
||||
'whoCanTakeTopics': 'acl',
|
||||
'whoCanUnassignTopic': 'acl',
|
||||
'whoCanUnmarkFavoriteReplyOnAnyTopic': 'acl',
|
||||
'favoriteRepliesOnTop': True,
|
||||
}
|
||||
GROUP_SETTINGS_LIST_ATTRIBUTES = set([
|
||||
# ACL choices
|
||||
'whoCanAdd',
|
||||
'whoCanApproveMembers',
|
||||
'whoCanApproveMessages',
|
||||
'whoCanAssignTopics',
|
||||
'whoCanAssistContent',
|
||||
'whoCanBanUsers',
|
||||
'whoCanContactOwner',
|
||||
'whoCanDeleteAnyPost',
|
||||
'whoCanDeleteTopics',
|
||||
'whoCanDiscoverGroup',
|
||||
'whoCanEnterFreeFormTags',
|
||||
'whoCanHideAbuse',
|
||||
'whoCanInvite',
|
||||
'whoCanJoin',
|
||||
'whoCanLeaveGroup',
|
||||
'whoCanLockTopics',
|
||||
'whoCanMakeTopicsSticky',
|
||||
'whoCanMarkDuplicate',
|
||||
'whoCanMarkFavoriteReplyOnAnyTopic',
|
||||
'whoCanMarkFavoriteReplyOnOwnTopic',
|
||||
'whoCanMarkNoResponseNeeded',
|
||||
'whoCanModerateContent',
|
||||
'whoCanModerateMembers',
|
||||
'whoCanModifyMembers',
|
||||
'whoCanModifyTagsAndCategories',
|
||||
'whoCanMoveTopicsIn',
|
||||
'whoCanMoveTopicsOut',
|
||||
'whoCanPostAnnouncements',
|
||||
'whoCanPostMessage',
|
||||
'whoCanTakeTopics',
|
||||
'whoCanUnassignTopic',
|
||||
'whoCanUnmarkFavoriteReplyOnAnyTopic',
|
||||
'whoCanViewGroup',
|
||||
'whoCanViewMembership',
|
||||
# Miscellaneous hoices
|
||||
'messageModerationLevel',
|
||||
'replyTo',
|
||||
'spamModerationLevel',
|
||||
])
|
||||
GROUP_SETTINGS_BOOLEAN_ATTRIBUTES = set([
|
||||
'allowExternalMembers',
|
||||
'allowGoogleCommunication',
|
||||
'allowWebPosting',
|
||||
'archiveOnly',
|
||||
'enableCollaborativeInbox',
|
||||
'favoriteRepliesOnTop',
|
||||
'includeCustomFooter',
|
||||
'includeInGlobalAddressList',
|
||||
'isArchived',
|
||||
'membersCanPostAsTheGroup',
|
||||
'sendMessageDenyNotification',
|
||||
'showInGroupDirectory',
|
||||
])
|
||||
|
||||
#
|
||||
# Global variables
|
||||
|
||||
Reference in New Issue
Block a user