Files
GoogleDriveManagement/src/gam/constants.py
2026-07-04 05:37:34 -04:00

553 lines
26 KiB
Python

"""GAM shared constants.
Return codes, Drive query fragments, choice maps, and other constants
shared across cmd/ modules.
"""
import platform
import re
import string
import sys
from gamlib import glcfg as GC
# Version and author (canonical source: gam/__init__.py)
from gam import __author__, __version__, __license__
# Time formats
IS08601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S%:z'
RFC2822_TIME_FORMAT = '%a, %d %b %Y %H:%M:%S %z'
# Application name
GIT_USER = 'GAM-team'
GAM = 'GAM'
GAM_PROJECT_CREATION = 'GAM Project Creation'
GAM_PROJECT_CREATION_CLIENT_ID = '297408095146-fug707qsjv4ikron0hugpevbrjhkmsk7.apps.googleusercontent.com'
# Byte sizes
ONE_KILO_BYTES = 1024
ONE_MEGA_BYTES = ONE_KILO_BYTES * ONE_KILO_BYTES
ONE_GIGA_BYTES = ONE_KILO_BYTES * ONE_MEGA_BYTES
ONE_TERA_BYTES = ONE_KILO_BYTES * ONE_GIGA_BYTES
# Day names
DAYS_OF_WEEK = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
# Time constants
MAX_LOCAL_GOOGLE_TIME_OFFSET = 30
# Character sets
LOWERNUMERIC_CHARS = string.ascii_lowercase + string.digits
ALPHANUMERIC_CHARS = LOWERNUMERIC_CHARS + string.ascii_uppercase
PASSWORD_SAFE_CHARS = ALPHANUMERIC_CHARS + '!#$%&()*-./:;<=>?@[\\\\]^_{|}~'
# Google Meet
GOOGLE_MEETID_PATTERN = re.compile(r'^[a-z]{3}-[a-z]{4}-[a-z]{3}$')
GOOGLE_MEETID_FORMAT_REQUIRED = 'abc-defg-hij'
GOOGLE_TIMECHECK_LOCATION = 'admin.googleapis.com'
# Drive constants
MY_DRIVE = 'My Drive'
TEAM_DRIVE = 'Drive'
ROOT = 'root'
# Access options
ADMIN_ACCESS_OPTIONS = {'adminaccess', 'asadmin'}
OWNER_ACCESS_OPTIONS = {'owneraccess', 'asowner'}
# Choice maps
PROJECTION_CHOICE_MAP = {'basic': 'BASIC', 'full': 'FULL'}
# Google API MIME types
APPLICATION_VND_GOOGLE_APPS = 'application/vnd.google-apps.'
MIMETYPE_GA_FOLDER = f'{APPLICATION_VND_GOOGLE_APPS}folder'
MIMETYPE_GA_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}shortcut'
# Queries
ME_IN_OWNERS = "'me' in owners"
ME_IN_OWNERS_AND = ME_IN_OWNERS + " and "
AND_ME_IN_OWNERS = " and " + ME_IN_OWNERS
NOT_ME_IN_OWNERS = "not " + ME_IN_OWNERS
NOT_ME_IN_OWNERS_AND = NOT_ME_IN_OWNERS + " and "
AND_NOT_ME_IN_OWNERS = " and " + NOT_ME_IN_OWNERS
ANY_FOLDERS = "mimeType = '" + MIMETYPE_GA_FOLDER + "'"
NON_TRASHED = "trashed = false"
WITH_PARENTS = "'{0}' in parents"
ANY_NON_TRASHED_WITH_PARENTS = "trashed = false and '{0}' in parents"
ANY_NON_TRASHED_FOLDER_NAME = "mimeType = '" + MIMETYPE_GA_FOLDER + "' and name = '{0}' and trashed = false"
MY_NON_TRASHED_FOLDER_NAME = ME_IN_OWNERS_AND + ANY_NON_TRASHED_FOLDER_NAME
MY_NON_TRASHED_FOLDER_NAME_WITH_PARENTS = ME_IN_OWNERS_AND + "mimeType = '" + MIMETYPE_GA_FOLDER + "' and name = '{0}' and trashed = false and '{1}' in parents"
ANY_NON_TRASHED_FOLDER_NAME_WITH_PARENTS = "mimeType = '" + MIMETYPE_GA_FOLDER + "' and name = '{0}' and trashed = false and '{1}' in parents"
AND_NOT_SHORTCUT = " and mimeType != '" + MIMETYPE_GA_SHORTCUT + "'"
# Program return codes
UNKNOWN_ERROR_RC = 1
USAGE_ERROR_RC = 2
SOCKET_ERROR_RC = 3
GOOGLE_API_ERROR_RC = 4
NETWORK_ERROR_RC = 5
FILE_ERROR_RC = 6
MEMORY_ERROR_RC = 7
KEYBOARD_INTERRUPT_RC = 8
HTTP_ERROR_RC = 9
SCOPES_NOT_AUTHORIZED_RC = 10
DATA_ERROR_RC = 11
API_ACCESS_DENIED_RC = 12
CONFIG_ERROR_RC = 13
SYSTEM_ERROR_RC = 14
NO_SCOPES_FOR_API_RC = 15
CLIENT_SECRETS_JSON_REQUIRED_RC = 16
OAUTH2SERVICE_JSON_REQUIRED_RC = 16
OAUTH2_TXT_REQUIRED_RC = 16
INVALID_JSON_RC = 17
JSON_ALREADY_EXISTS_RC = 17
AUTHENTICATION_TOKEN_REFRESH_ERROR_RC = 18
HARD_ERROR_RC = 19
# Information
ENTITY_IS_A_USER_RC = 20
ENTITY_IS_A_USER_ALIAS_RC = 21
ENTITY_IS_A_GROUP_RC = 22
ENTITY_IS_A_GROUP_ALIAS_RC = 23
ENTITY_IS_AN_UNMANAGED_ACCOUNT_RC = 24
ORGUNIT_NOT_EMPTY_RC = 25
USER_SUSPENDED_RC = 26
CHECK_USER_GROUPS_ERROR_RC = 29
ORPHANS_COLLECTED_RC = 30
# Warnings/Errors
ACTION_FAILED_RC = 50
ACTION_NOT_PERFORMED_RC = 51
INVALID_ENTITY_RC = 52
BAD_REQUEST_RC = 53
ENTITY_IS_NOT_UNIQUE_RC = 54
DATA_NOT_AVALIABLE_RC = 55
ENTITY_DOES_NOT_EXIST_RC = 56
ENTITY_DUPLICATE_RC = 57
ENTITY_IS_NOT_AN_ALIAS_RC = 58
ENTITY_IS_UKNOWN_RC = 59
NO_ENTITIES_FOUND_RC = 60
INVALID_DOMAIN_RC = 61
INVALID_DOMAIN_VALUE_RC = 62
INVALID_TOKEN_RC = 63
JSON_LOADS_ERROR_RC = 64
MULTIPLE_DELETED_USERS_FOUND_RC = 65
MULTIPLE_PROJECT_FOLDERS_FOUND_RC = 65
STDOUT_STDERR_ERROR_RC = 66
INSUFFICIENT_PERMISSIONS_RC = 67
REQUEST_COMPLETED_NO_RESULTS_RC = 71
REQUEST_NOT_COMPLETED_RC = 72
SERVICE_NOT_APPLICABLE_RC = 73
TARGET_DRIVE_SPACE_ERROR_RC = 74
USER_REQUIRED_TO_CHANGE_PASSWORD_ERROR_RC = 75
USER_SUSPENDED_ERROR_RC = 76
NO_CSV_DATA_TO_UPLOAD_RC = 77
NO_SA_ACCESS_CONTEXT_MANAGER_EDITOR_ROLE_RC = 78
ACCESS_POLICY_ERROR_RC = 79
YUBIKEY_CONNECTION_ERROR_RC = 80
YUBIKEY_INVALID_KEY_TYPE_RC = 81
YUBIKEY_INVALID_SLOT_RC = 82
YUBIKEY_INVALID_PIN_RC = 83
YUBIKEY_APDU_ERROR_RC = 84
YUBIKEY_VALUE_ERROR_RC = 85
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
YUBIKEY_NOT_FOUND_RC = 87
# Boolean constants
TRUE = 'true'
FALSE = 'false'
TRUE_VALUES = [TRUE, 'on', 'yes', 'enabled', '1']
FALSE_VALUES = [FALSE, 'off', 'no', 'disabled', '0']
TRUE_FALSE = [TRUE, FALSE]
# Error/warning prefixes
ERROR = 'ERROR'
ERROR_PREFIX = ERROR + ': '
WARNING = 'WARNING'
WARNING_PREFIX = WARNING + ': '
# Byte sizes (powers of 10)
ONE_KILO_10_BYTES = 1000
ONE_MEGA_10_BYTES = ONE_KILO_10_BYTES * ONE_KILO_10_BYTES
ONE_GIGA_10_BYTES = ONE_KILO_10_BYTES * ONE_MEGA_10_BYTES
ONE_TERA_10_BYTES = ONE_KILO_10_BYTES * ONE_GIGA_10_BYTES
# Time durations in seconds
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR = 3600
SECONDS_PER_DAY = 86400
SECONDS_PER_WEEK = 604800
# Google limits
MAX_GOOGLE_SHEET_CELLS = 10000000 # See https://support.google.com/drive/answer/37603
SHARED_DRIVE_MAX_FILES_FOLDERS = 500000
# Encoding
UTF8 = 'utf-8'
UTF8_SIG = 'utf-8-sig'
# Environment variable names
EV_GAMCFGDIR = 'GAMCFGDIR'
EV_GAMCFGSECTION = 'GAMCFGSECTION'
EV_OLDGAMPATH = 'OLDGAMPATH'
# Config file names
FN_GAM_CFG = 'gam.cfg'
FN_LAST_UPDATE_CHECK_TXT = 'lastupdatecheck.txt'
FN_GAMCOMMANDS_TXT = 'GamCommands.txt'
# Drive path constants
ROOTID = 'rootid'
ORPHANS = 'Orphans'
SHARED_WITHME = 'SharedWithMe'
SHARED_DRIVES = 'SharedDrives'
# Additional character sets
URL_SAFE_CHARS = ALPHANUMERIC_CHARS + '-._~'
FILENAME_SAFE_CHARS = ALPHANUMERIC_CHARS + "-_.() "
CHAT_MESSAGEID_CHARS = string.ascii_lowercase + string.digits + '-'
# File mode constants
DEFAULT_CSV_READ_MODE = 'r'
DEFAULT_FILE_APPEND_MODE = 'a'
DEFAULT_FILE_READ_MODE = 'r'
DEFAULT_FILE_WRITE_MODE = 'w'
# Application URLs
GAM_URL = f'https://github.com/{GIT_USER}/{GAM}'
GAM_RELEASES = f'https://github.com/{GIT_USER}/{GAM}/releases'
GAM_WIKI = f'https://github.com/{GIT_USER}/{GAM}/wiki'
GAM_LATEST_RELEASE = f'https://api.github.com/repos/{GIT_USER}/{GAM}/releases/latest'
GAM_USER_AGENT = (f'{GAM} {__version__} - {GAM_URL} / '
f'{__author__} / '
f'Python {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]} {sys.version_info[3]} / '
f'{platform.platform()} {platform.machine()} /'
)
# Additional Google API MIME types
MIMETYPE_GA_DOCUMENT = f'{APPLICATION_VND_GOOGLE_APPS}document'
MIMETYPE_GA_DRAWING = f'{APPLICATION_VND_GOOGLE_APPS}drawing'
MIMETYPE_GA_FILE = f'{APPLICATION_VND_GOOGLE_APPS}file'
MIMETYPE_GA_FORM = f'{APPLICATION_VND_GOOGLE_APPS}form'
MIMETYPE_GA_FUSIONTABLE = f'{APPLICATION_VND_GOOGLE_APPS}fusiontable'
MIMETYPE_GA_JAM = f'{APPLICATION_VND_GOOGLE_APPS}jam'
MIMETYPE_GA_MAP = f'{APPLICATION_VND_GOOGLE_APPS}map'
MIMETYPE_GA_PRESENTATION = f'{APPLICATION_VND_GOOGLE_APPS}presentation'
MIMETYPE_GA_SCRIPT = f'{APPLICATION_VND_GOOGLE_APPS}script'
MIMETYPE_GA_SCRIPT_JSON = f'{APPLICATION_VND_GOOGLE_APPS}script+json'
MIMETYPE_GA_3P_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}drive-sdk'
MIMETYPE_GA_SITE = f'{APPLICATION_VND_GOOGLE_APPS}site'
MIMETYPE_GA_SPREADSHEET = f'{APPLICATION_VND_GOOGLE_APPS}spreadsheet'
MIMETYPE_TEXT_CSV = 'text/csv'
MIMETYPE_TEXT_HTML = 'text/html'
MIMETYPE_TEXT_PLAIN = 'text/plain'
# Google infrastructure
GOOGLE_NAMESERVERS = ['8.8.8.8', '8.8.4.4']
# Date/time sentinel values
NEVER_DATE = '1970-01-01'
NEVER_DATETIME = '1970-01-01 00:00'
NEVER_TIME = '1970-01-01T00:00:00.000Z'
NEVER_TIME_NOMS = '1970-01-01T00:00:00Z'
NEVER_END_DATE = '1969-12-31'
NEVER_START_DATE = NEVER_DATE
REFRESH_EXPIRY = '1970-01-01T00:00:01Z'
UNKNOWN = 'Unknown'
REPLACE_GROUP_PATTERN = re.compile(r'\\(\d+)')
# Additional Drive query fragments
MY_FOLDERS = ME_IN_OWNERS_AND + ANY_FOLDERS
WITH_ANY_FILE_NAME = "name = '{0}'"
WITH_MY_FILE_NAME = ME_IN_OWNERS_AND + WITH_ANY_FILE_NAME
WITH_OTHER_FILE_NAME = NOT_ME_IN_OWNERS_AND + WITH_ANY_FILE_NAME
# Debug redaction patterns
DEBUG_REDACTION_PATTERNS = [
# Positional patterns that redact sensitive credentials based on their location
(r'(Bearer\s+)\S+', r'\1*****'), # access tokens and JWTs in auth header
(r'([?&]refresh_token=)[^&]*', r'\1*****'), # refresh token URL parameter
(r'([?&]client_secret=)[^&]*', r'\1*****'), # client secret URL parameter
(r'([?&]key=)[^&]*', r'\1*****'), # API key URL parameter
(r'([?&]code=)[^&]*', r'\1*****'), # auth code URL parameter
# Pattern match patterns that redact sensitive credentials based on known credential pattern
(r'ya29.[0-9A-Za-z-_]+', '*****'), # Access token
(r'1%2F%2F[0-9A-Za-z-_]{100}|1%2F%2F[0-9A-Za-z-_]{64}|1%2F%2F[0-9A-Za-z-_]{43}', '*****'), # Refresh token
(r'4/[0-9A-Za-z-_]+', '*****'), # Auth code
(r'GOCSPX-[0-9a-zA-Z-_]{28}', '*****'), # Client secret
(r'AIza[0-9A-Za-z-_]{35}', '*****'), # API key
(r'eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]*', '*****'), # JWT
]
# Building address field map
BUILDING_ADDRESS_FIELD_MAP = {
'address': 'addressLines',
'addresslines': 'addressLines',
'administrativearea': 'administrativeArea',
'city': 'locality',
'country': 'regionCode',
'language': 'languageCode',
'languagecode': 'languageCode',
'locality': 'locality',
'postalcode': 'postalCode',
'regioncode': 'regionCode',
'state': 'administrativeArea',
'sublocality': 'sublocality',
'zipcode': 'postalCode',
}
# Alias target types (moved from cmd/orgunits.py)
ALIAS_TARGET_TYPES = ['user', 'group', 'target']
# Info/display option sets (moved from cmd/groups/members.py, cmd/users/manage.py)
INFO_GROUP_OPTIONS = {'nousers', 'groups'}
INFO_USER_OPTIONS = {'noaliases', 'nobuildingnames', 'nogroups', 'nolicenses', 'nolicences', 'noschemas', 'schemas', 'userview'}
USER_SKIP_OBJECTS = {'thumbnailPhotoEtag'}
USER_TIME_OBJECTS = {'creationTime', 'deletionTime', 'lastLoginTime', 'suspensionTime', 'archivalTime', 'disabledTime'}
# License constants (moved from cmd/userop/usergroups.py)
LICENSE_PRODUCT_SKUIDS = 'productSkuIds'
# Drive file attribute keys (moved from cmd/drive/core.py)
DFA_URL = 'url'
# User fields choice map (moved from cmd/users/manage.py)
USER_FIELDS_CHOICE_MAP = {
'address': 'addresses',
'addresses': 'addresses',
'admin': ['isAdmin', 'isDelegatedAdmin'],
'agreed2terms': 'agreedToTerms',
'agreedtoterms': 'agreedToTerms',
'aliases': ['aliases', 'nonEditableAliases'],
'archived': ['archived', 'archivalTime'],
'changepassword': 'changePasswordAtNextLogin',
'changepasswordatnextlogin': 'changePasswordAtNextLogin',
'creationtime': 'creationTime',
'customerid': 'customerId',
'deletiontime': 'deletionTime',
'displayname': 'name.displayName',
'email': 'emails',
'emails': 'emails',
'employeeid': 'externalIds',
'externalid': 'externalIds',
'externalids': 'externalIds',
'familyname': 'name.familyName',
'firstname': 'name.givenName',
'fullname': 'name.fullName',
'gal': 'includeInGlobalAddressList',
'gender': ['gender.type', 'gender.customGender', 'gender.addressMeAs'],
'givenname': 'name.givenName',
'guestaccountinfo': ['guestAccountInfo.primaryGuestEmail'],
'id': 'id',
'im': 'ims',
'ims': 'ims',
'includeinglobaladdresslist': 'includeInGlobalAddressList',
'ipwhitelisted': 'ipWhitelisted',
'isadmin': ['isAdmin', 'isDelegatedAdmin'],
'isdelegatedadmin': ['isAdmin', 'isDelegatedAdmin'],
'isenforcedin2sv': 'isEnforcedIn2Sv',
'isenrolledin2sv': 'isEnrolledIn2Sv',
'isguestuser': 'isGuestUser',
'is2svenforced': 'isEnforcedIn2Sv',
'is2svenrolled': 'isEnrolledIn2Sv',
'ismailboxsetup': 'isMailboxSetup',
'keyword': 'keywords',
'keywords': 'keywords',
'language': 'languages',
'languages': 'languages',
'lastlogintime': 'lastLoginTime',
'lastname': 'name.familyName',
'location': 'locations',
'locations': 'locations',
'manager': 'relations',
'name': ['name.givenName', 'name.familyName', 'name.fullName', 'name.displayName'],
'nicknames': ['aliases', 'nonEditableAliases'],
'noneditablealiases': ['aliases', 'nonEditableAliases'],
'note': 'notes',
'notes': 'notes',
'org': 'orgUnitPath',
'organization': 'organizations',
'organizations': 'organizations',
'organisation': 'organizations',
'organisations': 'organizations',
'orgunit': 'orgUnitPath',
'orgunitpath': 'orgUnitPath',
'otheremail': 'emails',
'otheremails': 'emails',
'ou': 'orgUnitPath',
'phone': 'phones',
'phones': 'phones',
'photo': 'thumbnailPhotoUrl',
'photourl': 'thumbnailPhotoUrl',
'posix': 'posixAccounts',
'posixaccounts': 'posixAccounts',
'primaryemail': 'primaryEmail',
'recoveryemail': 'recoveryEmail',
'recoveryphone': 'recoveryPhone',
'relation': 'relations',
'relations': 'relations',
'ssh': 'sshPublicKeys',
'sshkeys': 'sshPublicKeys',
'sshpublickeys': 'sshPublicKeys',
'suspended': ['suspended', 'suspensionReason', 'suspensionTime'],
'thumbnailphotourl': 'thumbnailPhotoUrl',
'username': 'primaryEmail',
'website': 'websites',
'websites': 'websites',
}
# Group settings choice maps (moved from cmd/mobile.py)
GROUP_DISCOVER_CHOICES = {
'allmemberscandiscover': 'ALL_MEMBERS_CAN_DISCOVER',
'allindomaincandiscover': 'ALL_IN_DOMAIN_CAN_DISCOVER',
'anyonecandiscover': 'ANYONE_CAN_DISCOVER',
}
GROUP_ASSIST_CONTENT_CHOICES = {
'allmembers': 'ALL_MEMBERS',
'ownersandmanagers': 'OWNERS_AND_MANAGERS',
'managersonly': 'MANAGERS_ONLY',
'ownersonly': 'OWNERS_ONLY',
'none': 'NONE',
}
GROUP_MODERATE_CONTENT_CHOICES = {
'allmembers': 'ALL_MEMBERS',
'ownersandmanagers': 'OWNERS_AND_MANAGERS',
'ownersonly': 'OWNERS_ONLY',
'none': 'NONE',
}
GROUP_MODERATE_MEMBERS_CHOICES = {
'allmembers': 'ALL_MEMBERS',
'ownersandmanagers': 'OWNERS_AND_MANAGERS',
'ownersonly': 'OWNERS_ONLY',
'none': 'NONE',
}
# Group settings attribute maps (moved from cmd/mobile.py)
GROUP_DEPRECATED_ATTRIBUTES = {
'allowgooglecommunication': ['allowGoogleCommunication', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'favoriterepliesontop': ['favoriteRepliesOnTop', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'maxmessagebytes': ['maxMessageBytes', {GC.VAR_TYPE: GC.TYPE_INTEGER, GC.VAR_LIMITS: (1024, 1048576)}],
'messagedisplayfont': ['messageDisplayFont', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'defaultfont': 'DEFAULT_FONT', 'fixedwidthfont': 'FIXED_WIDTH_FONT'}}],
'whocanaddreferences': ['whoCanAddReferences', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmarkfavoritereplyonowntopic': ['whoCanMarkFavoriteReplyOnOwnTopic', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
}
GROUP_DISCOVER_ATTRIBUTES = {
'showingroupdirectory': ['showInGroupDirectory', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
}
GROUP_ASSIST_CONTENT_ATTRIBUTES = {
'whocanassigntopics': ['whoCanAssignTopics', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanenterfreeformtags': ['whoCanEnterFreeFormTags', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanhideabuse': ['whoCanHideAbuse', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmaketopicssticky': ['whoCanMakeTopicsSticky', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmarkduplicate': ['whoCanMarkDuplicate', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmarkfavoritereplyonanytopic': ['whoCanMarkFavoriteReplyOnAnyTopic', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmarknoresponseneeded': ['whoCanMarkNoResponseNeeded', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmodifytagsandcategories': ['whoCanModifyTagsAndCategories', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocantaketopics': ['whoCanTakeTopics', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanunassigntopic': ['whoCanUnassignTopic', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanunmarkfavoritereplyonanytopic': ['whoCanUnmarkFavoriteReplyOnAnyTopic', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
}
GROUP_MODERATE_CONTENT_ATTRIBUTES = {
'whocanapprovemessages': ['whoCanApproveMessages', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocandeleteanypost': ['whoCanDeleteAnyPost', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocandeletetopics': ['whoCanDeleteTopics', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocanlocktopics': ['whoCanLockTopics', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocanmovetopicsin': ['whoCanMoveTopicsIn', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocanmovetopicsout': ['whoCanMoveTopicsOut', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocanpostannouncements': ['whoCanPostAnnouncements', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
}
GROUP_MODERATE_MEMBERS_ATTRIBUTES = {
'whocanadd': ['whoCanAdd', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allmanagerscanadd': 'ALL_MANAGERS_CAN_ADD', 'allownerscanadd': 'ALL_OWNERS_CAN_ADD',
'allmemberscanadd': 'ALL_MEMBERS_CAN_ADD', 'nonecanadd': 'NONE_CAN_ADD'}}],
'whocanapprovemembers': ['whoCanApproveMembers', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allownerscanapprove': 'ALL_OWNERS_CAN_APPROVE', 'allmanagerscanapprove': 'ALL_MANAGERS_CAN_APPROVE',
'allmemberscanapprove': 'ALL_MEMBERS_CAN_APPROVE', 'nonecanapprove': 'NONE_CAN_APPROVE'}}],
'whocanbanusers': ['whoCanBanUsers', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_MEMBERS_CHOICES}],
'whocaninvite': ['whoCanInvite', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allmemberscaninvite': 'ALL_MEMBERS_CAN_INVITE', 'allmanagerscaninvite': 'ALL_MANAGERS_CAN_INVITE',
'allownerscaninvite': 'ALL_OWNERS_CAN_INVITE', 'nonecaninvite': 'NONE_CAN_INVITE'}}],
'whocanmodifymembers': ['whoCanModifyMembers', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_MEMBERS_CHOICES}],
}
GROUP_BASIC_ATTRIBUTES = {
'description': ['description', {GC.VAR_TYPE: GC.TYPE_STRING}],
'name': ['name', {GC.VAR_TYPE: GC.TYPE_STRING}],
'displayname': ['name', {GC.VAR_TYPE: GC.TYPE_STRING}],
}
GROUP_SETTINGS_ATTRIBUTES = {
'allowexternalmembers': ['allowExternalMembers', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'allowwebposting': ['allowWebPosting', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'archiveonly': ['archiveOnly', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'customfootertext': ['customFooterText', {GC.VAR_TYPE: GC.TYPE_STRING}],
'customreplyto': ['customReplyTo', {GC.VAR_TYPE: GC.TYPE_EMAIL_OPTIONAL}],
'customrolesenabledforsettingstobemerged': ['customRolesEnabledForSettingsToBeMerged', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'defaultmessagedenynotificationtext': ['defaultMessageDenyNotificationText', {GC.VAR_TYPE: GC.TYPE_STRING}],
'defaultsender': ['defaultSender', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'self': 'DEFAULT_SELF', 'defaultself': 'DEFAULT_SELF', 'group': 'GROUP'}}],
'enablecollaborativeinbox': ['enableCollaborativeInbox', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'includecustomfooter': ['includeCustomFooter', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'includeinglobaladdresslist': ['includeInGlobalAddressList', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'isarchived': ['isArchived', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'memberscanpostasthegroup': ['membersCanPostAsTheGroup', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'messagemoderationlevel': ['messageModerationLevel', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'moderateallmessages': 'MODERATE_ALL_MESSAGES', 'moderatenonmembers': 'MODERATE_NON_MEMBERS',
'moderatenewmembers': 'MODERATE_NEW_MEMBERS', 'moderatenone': 'MODERATE_NONE'}}],
'primarylanguage': ['primaryLanguage', {GC.VAR_TYPE: GC.TYPE_LANGUAGE}],
'replyto': ['replyTo', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'replytocustom': 'REPLY_TO_CUSTOM', 'replytosender': 'REPLY_TO_SENDER', 'replytolist': 'REPLY_TO_LIST',
'replytoowner': 'REPLY_TO_OWNER', 'replytoignore': 'REPLY_TO_IGNORE', 'replytomanagers': 'REPLY_TO_MANAGERS'}}],
'sendmessagedenynotification': ['sendMessageDenyNotification', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'spammoderationlevel': ['spamModerationLevel', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allow': 'ALLOW', 'moderate': 'MODERATE', 'silentlymoderate': 'SILENTLY_MODERATE', 'reject': 'REJECT'}}],
'whocanaddexternalmembers': ['whoCanAddExternalMembers', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'onlyadminscanaddexternalmembers': 'ONLY_ADMINS_CAN_ADD_EXTERNAL_MEMBERS',
'enduserscanaddexternalmembers': 'END_USERS_CAN_ADD_EXTERNAL_MEMBERS'}}],
'whocancontactowner': ['whoCanContactOwner', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'anyonecancontact': 'ANYONE_CAN_CONTACT', 'allindomaincancontact': 'ALL_IN_DOMAIN_CAN_CONTACT',
'allmemberscancontact': 'ALL_MEMBERS_CAN_CONTACT', 'allmanagerscancontact': 'ALL_MANAGERS_CAN_CONTACT',
'allownerscancontact': 'ALL_OWNERS_CAN_CONTACT'}}],
'whocanjoin': ['whoCanJoin', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'anyonecanjoin': 'ANYONE_CAN_JOIN', 'allindomaincanjoin': 'ALL_IN_DOMAIN_CAN_JOIN',
'invitedcanjoin': 'INVITED_CAN_JOIN', 'canrequesttojoin': 'CAN_REQUEST_TO_JOIN'}}],
'whocanleavegroup': ['whoCanLeaveGroup', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allmanagerscanleave': 'ALL_MANAGERS_CAN_LEAVE', 'allownerscanleave': 'ALL_OWNERS_CAN_LEAVE',
'allmemberscanleave': 'ALL_MEMBERS_CAN_LEAVE', 'nonecanleave': 'NONE_CAN_LEAVE'}}],
'whocanpostmessage': ['whoCanPostMessage', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'nonecanpost': 'NONE_CAN_POST', 'allmanagerscanpost': 'ALL_MANAGERS_CAN_POST',
'allmemberscanpost': 'ALL_MEMBERS_CAN_POST', 'allownerscanpost': 'ALL_OWNERS_CAN_POST',
'allindomaincanpost': 'ALL_IN_DOMAIN_CAN_POST', 'anyonecanpost': 'ANYONE_CAN_POST'}}],
'whocanviewgroup': ['whoCanViewGroup', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'anyonecanview': 'ANYONE_CAN_VIEW', 'allindomaincanview': 'ALL_IN_DOMAIN_CAN_VIEW',
'allmemberscanview': 'ALL_MEMBERS_CAN_VIEW', 'allmanagerscanview': 'ALL_MANAGERS_CAN_VIEW',
'allownerscanview': 'ALL_OWNERS_CAN_VIEW'}}],
'whocanviewmembership': ['whoCanViewMembership', {GC.VAR_TYPE: GC.TYPE_CHOICE,
'choices': {'allindomaincanview': 'ALL_IN_DOMAIN_CAN_VIEW', 'allmemberscanview': 'ALL_MEMBERS_CAN_VIEW',
'allmanagerscanview': 'ALL_MANAGERS_CAN_VIEW', 'allownerscanview': 'ALL_OWNERS_CAN_VIEW'}}],
}
GROUP_ALIAS_ATTRIBUTES = {
'collaborative': ['enableCollaborativeInbox', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
'gal': ['includeInGlobalAddressList', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}],
}
GROUP_MERGED_ATTRIBUTES = {
'whocandiscovergroup': ['whoCanDiscoverGroup', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_DISCOVER_CHOICES}],
'whocanassistcontent': ['whoCanAssistContent', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_ASSIST_CONTENT_CHOICES}],
'whocanmoderatecontent': ['whoCanModerateContent', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_CONTENT_CHOICES}],
'whocanmoderatemembers': ['whoCanModerateMembers', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': GROUP_MODERATE_MEMBERS_CHOICES}],
}
GROUP_MERGED_ATTRIBUTES_PRINT_ORDER = ['whoCanDiscoverGroup', 'whoCanAssistContent', 'whoCanModerateContent', 'whoCanModerateMembers']
GROUP_MERGED_TO_COMPONENT_MAP = {
'whoCanDiscoverGroup': GROUP_DISCOVER_ATTRIBUTES,
'whoCanAssistContent': GROUP_ASSIST_CONTENT_ATTRIBUTES,
'whoCanModerateContent': GROUP_MODERATE_CONTENT_ATTRIBUTES,
'whoCanModerateMembers': GROUP_MODERATE_MEMBERS_ATTRIBUTES,
}
GROUP_ATTRIBUTES_SET = set(list(GROUP_BASIC_ATTRIBUTES)+list(GROUP_SETTINGS_ATTRIBUTES)+list(GROUP_ALIAS_ATTRIBUTES)+
list(GROUP_ASSIST_CONTENT_ATTRIBUTES)+list(GROUP_MODERATE_CONTENT_ATTRIBUTES)+list(GROUP_MODERATE_MEMBERS_ATTRIBUTES)+
list(GROUP_MERGED_ATTRIBUTES)+list(GROUP_DEPRECATED_ATTRIBUTES))
GROUP_FIELDS_WITH_CRS_NLS = {'customFooterText', 'defaultMessageDenyNotificationText', 'description'}
# Command routing table indices
CMD_ACTION = 0
CMD_FUNCTION = 1