mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-04 12:51:36 +00:00
Phase 2 (partial): Move constants and calendar ACL helpers
This commit is contained in:
@@ -93,12 +93,55 @@ from gam.util.errors import (
|
|||||||
unknownArgumentExit,
|
unknownArgumentExit,
|
||||||
)
|
)
|
||||||
from gam.util.fileio import UNKNOWN
|
from gam.util.fileio import UNKNOWN
|
||||||
from gam.util.output import executeBatch, setSysExitRC
|
from gam.util.output import executeBatch, formatKeyValueList, setSysExitRC
|
||||||
from gam.constants import DAYS_OF_WEEK, GOOGLE_MEETID_FORMAT_REQUIRED, GOOGLE_MEETID_PATTERN, NO_ENTITIES_FOUND_RC
|
from gam.constants import DAYS_OF_WEEK, GOOGLE_MEETID_FORMAT_REQUIRED, GOOGLE_MEETID_PATTERN, NO_ENTITIES_FOUND_RC
|
||||||
|
|
||||||
Act = glaction.GamAction()
|
Act = glaction.GamAction()
|
||||||
Ent = glentity.GamEntity()
|
Ent = glentity.GamEntity()
|
||||||
Ind = glindent.GamIndent()
|
Ind = glindent.GamIndent()
|
||||||
|
|
||||||
|
|
||||||
|
# ACL utility functions (moved from gam/__init__.py)
|
||||||
|
def ACLRuleDict(rule):
|
||||||
|
if rule['scope']['type'] != 'default':
|
||||||
|
return {'Scope': f'{rule["scope"]["type"]}:{rule["scope"]["value"]}', 'Role': rule['role']}
|
||||||
|
return {'Scope': f'{rule["scope"]["type"]}', 'Role': rule['role']}
|
||||||
|
|
||||||
|
def ACLRuleKeyValueList(rule):
|
||||||
|
if rule['scope']['type'] != 'default':
|
||||||
|
return ['Scope', f'{rule["scope"]["type"]}:{rule["scope"]["value"]}', 'Role', rule['role']]
|
||||||
|
return ['Scope', f'{rule["scope"]["type"]}', 'Role', rule['role']}
|
||||||
|
|
||||||
|
def formatACLRule(rule):
|
||||||
|
return formatKeyValueList('(', ACLRuleKeyValueList(rule), ')')
|
||||||
|
|
||||||
|
def formatACLScopeRole(scope, role):
|
||||||
|
if role:
|
||||||
|
return formatKeyValueList('(', ['Scope', scope, 'Role', role], ')')
|
||||||
|
return formatKeyValueList('(', ['Scope', scope], ')')
|
||||||
|
|
||||||
|
def normalizeRuleId(ruleId):
|
||||||
|
ruleIdParts = ruleId.split(':', 1)
|
||||||
|
if (len(ruleIdParts) == 1) or not ruleIdParts[1]:
|
||||||
|
if ruleIdParts[0] == 'default':
|
||||||
|
return ruleId
|
||||||
|
if ruleIdParts[0] == 'domain':
|
||||||
|
return f'domain:{GC.Values[GC.DOMAIN]}'
|
||||||
|
return f'user:{normalizeEmailAddressOrUID(ruleIdParts[0], noUid=True)}'
|
||||||
|
if ruleIdParts[0] in {'user', 'group'}:
|
||||||
|
return f'{ruleIdParts[0]}:{normalizeEmailAddressOrUID(ruleIdParts[1], noUid=True)}'
|
||||||
|
return ruleId
|
||||||
|
|
||||||
|
def makeRoleRuleIdBody(role, ruleId):
|
||||||
|
ruleIdParts = ruleId.split(':', 1)
|
||||||
|
if len(ruleIdParts) == 1:
|
||||||
|
if ruleIdParts[0] == 'default':
|
||||||
|
return {'role': role, 'scope': {'type': ruleIdParts[0]}}
|
||||||
|
if ruleIdParts[0] == 'domain':
|
||||||
|
return {'role': role, 'scope': {'type': ruleIdParts[0], 'value': GC.Values[GC.DOMAIN]}}
|
||||||
|
return {'role': role, 'scope': {'type': 'user', 'value': ruleIdParts[0]}}
|
||||||
|
return {'role': role, 'scope': {'type': ruleIdParts[0], 'value': ruleIdParts[1]}}
|
||||||
|
|
||||||
Cmd = glclargs.GamCLArgs()
|
Cmd = glclargs.GamCLArgs()
|
||||||
|
|
||||||
|
|
||||||
@@ -234,7 +277,6 @@ def _normalizeCalIdGetRuleIds(origUser, user, origCal, calId, j, jcount, ACLScop
|
|||||||
return (calId, cal, ruleIds, kcount)
|
return (calId, cal, ruleIds, kcount)
|
||||||
|
|
||||||
def _processCalendarACLs(cal, function, entityType, calId, j, jcount, k, kcount, role, ruleId, sendNotifications):
|
def _processCalendarACLs(cal, function, entityType, calId, j, jcount, k, kcount, role, ruleId, sendNotifications):
|
||||||
from gam import formatACLScopeRole, makeRoleRuleIdBody
|
|
||||||
result = True
|
result = True
|
||||||
if function == 'insert':
|
if function == 'insert':
|
||||||
kwargs = {'body': makeRoleRuleIdBody(role, ruleId), 'fields': '', 'sendNotifications': sendNotifications}
|
kwargs = {'body': makeRoleRuleIdBody(role, ruleId), 'fields': '', 'sendNotifications': sendNotifications}
|
||||||
@@ -264,7 +306,6 @@ def _processCalendarACLs(cal, function, entityType, calId, j, jcount, k, kcount,
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def _createCalendarACLs(cal, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
def _createCalendarACLs(cal, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
||||||
from gam import normalizeRuleId
|
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
k = 0
|
k = 0
|
||||||
for ruleId in ruleIds:
|
for ruleId in ruleIds:
|
||||||
@@ -294,7 +335,6 @@ def doCalendarsCreateACLs(calIds):
|
|||||||
_doCalendarsCreateACLs(None, None, None, calIds, len(calIds), role, ACLScopeEntity, sendNotifications)
|
_doCalendarsCreateACLs(None, None, None, calIds, len(calIds), role, ACLScopeEntity, sendNotifications)
|
||||||
|
|
||||||
def _updateDeleteCalendarACLs(cal, function, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
def _updateDeleteCalendarACLs(cal, function, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
||||||
from gam import normalizeRuleId
|
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
k = 0
|
k = 0
|
||||||
for ruleId in ruleIds:
|
for ruleId in ruleIds:
|
||||||
@@ -334,7 +374,6 @@ def doCalendarsDeleteACLs(calIds):
|
|||||||
_doUpdateDeleteCalendarACLs(None, None, None, 'delete', calIds, len(calIds), ACLScopeEntity, role, False)
|
_doUpdateDeleteCalendarACLs(None, None, None, 'delete', calIds, len(calIds), ACLScopeEntity, role, False)
|
||||||
|
|
||||||
def _showCalendarACL(user, entityType, calId, acl, k, kcount, FJQC):
|
def _showCalendarACL(user, entityType, calId, acl, k, kcount, FJQC):
|
||||||
from gam import ACLRuleKeyValueList
|
|
||||||
if FJQC.formatJSON:
|
if FJQC.formatJSON:
|
||||||
if entityType == Ent.CALENDAR:
|
if entityType == Ent.CALENDAR:
|
||||||
if user:
|
if user:
|
||||||
@@ -350,7 +389,6 @@ def _showCalendarACL(user, entityType, calId, acl, k, kcount, FJQC):
|
|||||||
printKeyValueListWithCount(ACLRuleKeyValueList(acl), k, kcount)
|
printKeyValueListWithCount(ACLRuleKeyValueList(acl), k, kcount)
|
||||||
|
|
||||||
def _infoCalendarACLs(cal, user, entityType, calId, j, jcount, ruleIds, kcount, FJQC):
|
def _infoCalendarACLs(cal, user, entityType, calId, j, jcount, ruleIds, kcount, FJQC):
|
||||||
from gam import formatACLScopeRole, normalizeRuleId
|
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
k = 0
|
k = 0
|
||||||
for ruleId in ruleIds:
|
for ruleId in ruleIds:
|
||||||
|
|||||||
@@ -673,7 +673,7 @@ RESOURCE_FIELDS_WITH_CRS_NLS = {'resourceDescription'}
|
|||||||
|
|
||||||
def _showResource(cd, resource, i, count, FJQC, acls=None, noSelfOwner=False):
|
def _showResource(cd, resource, i, count, FJQC, acls=None, noSelfOwner=False):
|
||||||
|
|
||||||
from gam import ACLRuleKeyValueList
|
from gam.cmd.calendar import ACLRuleKeyValueList
|
||||||
def _showResourceField(title, resource, field):
|
def _showResourceField(title, resource, field):
|
||||||
if field in resource:
|
if field in resource:
|
||||||
if field not in RESOURCE_FIELDS_WITH_CRS_NLS:
|
if field not in RESOURCE_FIELDS_WITH_CRS_NLS:
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ def _getCalendarAttributes(body, returnOnUnknownArgument=False):
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
|
|
||||||
def _showCalendar(calendar, j, jcount, FJQC, acls=None):
|
def _showCalendar(calendar, j, jcount, FJQC, acls=None):
|
||||||
from gam import ACLRuleKeyValueList
|
from gam.cmd.calendar import ACLRuleKeyValueList
|
||||||
if FJQC.formatJSON:
|
if FJQC.formatJSON:
|
||||||
if acls:
|
if acls:
|
||||||
calendar['acls'] = [{'id': rule['id'], 'role': rule['role']} for rule in acls]
|
calendar['acls'] = [{'id': rule['id'], 'role': rule['role']} for rule in acls]
|
||||||
|
|||||||
@@ -146,6 +146,129 @@ YUBIKEY_VALUE_ERROR_RC = 85
|
|||||||
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
|
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
|
||||||
YUBIKEY_NOT_FOUND_RC = 87
|
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'
|
||||||
|
|
||||||
|
# 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
|
||||||
BUILDING_ADDRESS_FIELD_MAP = {
|
BUILDING_ADDRESS_FIELD_MAP = {
|
||||||
'address': 'addressLines',
|
'address': 'addressLines',
|
||||||
|
|||||||
Reference in New Issue
Block a user