Multiple fixes (#713)

* - Update new create drive options
* - Add gender, keyword, languages attributes to user
This commit is contained in:
Ross Scroggs
2018-03-28 15:01:49 -07:00
committed by Jay Lee
parent ce2e379f30
commit 16636c34b5
3 changed files with 144 additions and 49 deletions

View File

@ -436,6 +436,7 @@ Named items
email|emails|otheremail|otheremails|
externalids|externalid|
familyname|firstname|fullname|givenname|lastname|name|
gender|
id|
ims|im|
includeinglobaladdresslist|gal|
@ -444,6 +445,8 @@ Named items
ismailboxsetup|
isenforcedin2sv|is2svenforced|
isenrolledin2sv|is2svenrolled|
keyword|keywords|
language|languages|
lastlogintime|
locations|location|
noneditablealiases|aliases|nicknames|
@ -463,11 +466,18 @@ Named items
familyname|lastname|givenname|firstname|email
Named Lists
Lists can be in the following formats
Items, separated by commas, without spaces or commas in the items themselves: item(,item)*
Items, separated by spaces, without spaces or commas in the items themselves: "item( item)*"
Items, separated by commas, with spaces or commas in the items themselves: "'it em'(,'it,em')*"
Items, separated by spaces, with spaces or commas in the items themselves: "'it em'( 'it,em')*"
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
Items, separated by commas, without spaces, commas or single quotes in the items themselves
"item,item,item"
Items, separated by spaces, without spaces, commas or single quotes in the items themselves
"item item item"
Items, separated by commas, with spaces, commas or single quotes in the items themselves
"'it em','it,em',\"it'em\""
Items, separated by spaces, with spaces, commas or single quotes in the items themselves
"'it em' 'it,em' \"it'em\""
<ACLList> ::= "<ACLScope>(,<ACLScope>)*"
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
@ -507,29 +517,29 @@ Items, separated by spaces, with spaces or commas in the items themselves: "'it
Specify a collection of ChromeOS devices by directly specifying them
<CrOSTypeEntity> ::=
(all cros)|
(cros <CrOSList>)|
(all cros)|
(cros <CrOSList>)|
Specify a collection of Users by directly specifying them or by specifiying items that will yield a list of users
<UserTypeEntity> ::=
(all users)|
(user <UserItem>)|
(users <UserList>)|
(group <GroupItem)|
(ou|org <OrgUnitPath)|
(ou_and_children|ou_and_child <OrgUnitPath>)|
(courseparticipants <CourseID>)|
(students <CourseID>)|
(teachers <CourseID>)|
(file <FileName>)|
(csvfile <FileName>:<FieldName>)|
(license|licenses|licence|licences <SKUIDList>)|
(query <QueryUser>)
(all users)|
(user <UserItem>)|
(users <UserList>)|
(group <GroupItem)|
(ou|org <OrgUnitPath)|
(ou_and_children|ou_and_child <OrgUnitPath>)|
(courseparticipants <CourseID>)|
(students <CourseID>)|
(teachers <CourseID>)|
(file <FileName>)|
(csvfile <FileName>:<FieldName>)|
(license|licenses|licence|licences <SKUIDList>)|
(query <QueryUser>)
Item attributes
<BuildingAttributes> ::=
(buildingid <String>)|
(description <String>)|
(floors <FloorNameList>)|
(id <String>)|
(latitude <Float>)|
(longitude <Float>)|
(name <String>)
@ -621,7 +631,7 @@ Item attributes
<ResourceAttributes> ::=
(buildingid <BuildingID>)|
(capacity <Number>)|
(category other|room|conference_room)|
(category other|room|conference_room|unknown_category)|
(description <String>)|
(features <FeatureNameList>)|
(floor <FloorName>)|
@ -646,8 +656,11 @@ Item attributes
(externalid clear|(account|customer|login_id|network|organization|<String> <String>))|
(firstname|givenname <String>)|
(gal|includeinglobaladdresslist <Boolean>)|
(gender clear|(female|male|unknown|(other <String>) [addressmeas <String>]))|
(im clear|(type work|home|other|(custom <String>) protocol aim|gtalk|icq|jabber|msn|net_meeting|qq|skype|yahoo|(custom_protocol <String>) <String> [notprimary|primary]))|
(ipwhitelisted <Boolean>)|
(keyword clear|(occupation|outlook|(custom <string>) <String>))|
(language clear|<LanguageList>)|
(lastname|familyname <String>)|
(location clear|(type default|desk|<String> area <String> [building|buildingid <BuildingID>] [floor|floorname <FloorName>] [section|floorsection <String>] [desk|deskcode <String>] endlocation))|
(note clear|([text_plain|text_html] <String>|(file <FileName> [charset <Charset>])))|
@ -821,13 +834,6 @@ Prints no header row and deviceId for specified CrOS devices.
gam print cros ... basic|full
Prints a header row and selected fields for specified CrOS devices.
Print a header row and selected fields for specified CrOS devices; deviceId is the always the first column.
If you specify allfields|basic|full, all other column headers are sorted.
If you specify <CrOSFieldName>* | fields <CrOSFieldNameList>, the column headers appear in the order specified.
gam [<CrOSTypeEntity>] print cros [todrive [<ToDriveAttributes>]] [query <QueryCrOS>]|[select <CrOSTypeEntity>] [limittoou <OrgUnitItem>]
[orderby <CrOSOrderByFieldName> [ascending|descending]] [nolists|recentusers|timeranges|devicefiles] [listlimit <Number>] [start <Date>] [end <Date>]
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
The basic argument outputs these column headers: deviceId,annotatedAssetId,annotatedLocation,annotatedUser,lastSync,notes,serialNumber,status
The allfields/full arguments output all column headers including three headers, recentUsers, activeTimeRanges and deviceFiles,
that repeat with two/four/two subvalues each, yielding a large number of columns that make the output hard to process.
@ -1039,7 +1045,7 @@ gam <UserTypeEntity> show fileinfo <DriveFileID> [allfields|<DriveFieldName>*]
gam <UserTypeEntity> show filerevisions <DriveFileID>
gam <UserTypeEntity> show filetree [anyowner] (orderby <DriveOrderByFieldName> [ascending|descending])*
gam <UserTypeEntity> create|add drivefile [drivefilename <DriveFileName>] <DriveFileAddAttributes>*
gam <UserTypeEntity> create|add drivefile [drivefilename <DriveFileName>] <DriveFileAddAttributes>* [csv] [todrive]
gam <UserTypeEntity> update drivefile (id <DriveFileID)|(drivefilename <DriveFileName>)|(query <QueryDriveFile) [copy] [newfilename <DriveFileName>] <DriveFileUpdateAttributes>*
gam <UserTypeEntity> get drivefile (id <DriveFileID>)|(drivefilename <DriveFileName>)|(query <QueryDriveFile>) [format <FileFormatList>] [targetfolder <FilePath>] [revision <Number>]
gam <UserTypeEntity> delete|del drivefile <DriveFileID>|<DriveFileURL>|(query:<QueryDriveFile>) [purge|untrash]

View File

@ -4346,7 +4346,7 @@ def getDriveFileAttribute(i, body, parameters, myarg, update=False):
parameters[DFA_OCR] = True
i += 1
elif myarg == u'ocrlanguage':
parameters[DFA_OCRLANGUAGE] = sys.argv[i+1]
parameters[DFA_OCRLANGUAGE] = LANGUAGE_CODES_MAP.get(sys.argv[i+1].lower(), sys.argv[i+1])
i += 2
elif myarg in DRIVEFILE_LABEL_CHOICES_MAP:
body.setdefault(u'labels', {})
@ -4461,9 +4461,9 @@ def doUpdateDriveFile(users):
print u'Successfully copied %s to %s' % (fileId, result[u'id'])
def createDriveFile(users):
csv_output = None
csv_output = to_drive = False
csv_rows = []
csv_titles = [u'title',u'id']
csv_titles = [u'User', u'title', u'id']
media_body = None
body, parameters = initializeDriveFileAttributes()
i = 5
@ -4475,6 +4475,9 @@ def createDriveFile(users):
elif myarg == u'csv':
csv_output = True
i += 1
elif myarg == u'todrive':
to_drive = True
i += 1
else:
i = getDriveFileAttribute(i, body, parameters, myarg, False)
for user in users:
@ -4495,17 +4498,14 @@ def createDriveFile(users):
supportsTeamDrives=True)
titleInfo = u'{0}({1})'.format(result[u'title'], result[u'id'])
if csv_output:
csv_rows.append({
u'title': result[u'title'],
u'id': result[u'id']
})
csv_rows.append({u'User': user, u'title': result[u'title'], u'id': result[u'id']})
else:
if parameters[DFA_LOCALFILENAME]:
print u'Successfully uploaded %s to Drive File %s' % (parameters[DFA_LOCALFILENAME], titleInfo)
else:
print u'Successfully created Drive %s %s' % ([u'Folder', u'File'][result[u'mimeType'] != MIMETYPE_GA_FOLDER], titleInfo)
if csv_output:
writeCSVfile(csv_rows, csv_titles, u'Files', False)
writeCSVfile(csv_rows, csv_titles, u'Files', to_drive)
def downloadDriveFile(users):
i = 5
@ -5475,7 +5475,7 @@ def doDeleteLabel(users):
bcount = 0
j = 0
del_me_count = len(del_labels)
dbatch = gmail.new_batch_http_request()
dbatch = gmail.new_batch_http_request()
for del_me in del_labels:
j += 1
print u' deleting label %s (%s/%s)' % (del_me[u'name'], j, del_me_count)
@ -6423,7 +6423,7 @@ def doGetUserSchema():
_showSchema(schema)
def getUserAttributes(i, cd, updateCmd=False):
def getEntryType(i, entry, entryTypes, setTypeCustom=True):
def getEntryType(i, entry, entryTypes, setTypeCustom=True, customKeyword=u'custom', customTypeKeyword=u'customType'):
""" Get attribute entry type
entryTypes is list of pre-defined types, a|b|c
Allow a|b|c|<String>, a|b|c|custom <String>
@ -6435,26 +6435,25 @@ def getUserAttributes(i, cd, updateCmd=False):
"""
utype = sys.argv[i]
ltype = utype.lower()
if ltype == u'custom':
if ltype == customKeyword:
i += 1
utype = sys.argv[i]
ltype = utype.lower()
if ltype in entryTypes:
entry[u'type'] = ltype
entry.pop(u'customType', None)
entry.pop(customTypeKeyword, None)
else:
entry[u'customType'] = utype
entry[customTypeKeyword] = utype
if setTypeCustom:
entry[u'type'] = u'custom'
entry[u'type'] = customKeyword
else:
entry.pop(u'type', None)
return i+1
def checkClearBodyList(i, body, itemName):
if sys.argv[i].lower() == u'clear':
if itemName in body:
del body[itemName]
body.setdefault(itemName, None)
body.pop(itemName, None)
body[itemName] = None
return True
return False
@ -6553,6 +6552,28 @@ def getUserAttributes(i, cd, updateCmd=False):
if body[u'orgUnitPath'][0] != u'/':
body[u'orgUnitPath'] = u'/%s' % body[u'orgUnitPath']
i += 2
elif myarg in [u'language', u'languages']:
i += 1
if checkClearBodyList(i, body, u'languages'):
i += 1
continue
for language in sys.argv[i].replace(u',', u' ').split():
if language.lower() in LANGUAGE_CODES_MAP:
appendItemToBodyList(body, u'languages', {u'languageCode': LANGUAGE_CODES_MAP[language.lower()]})
else:
appendItemToBodyList(body, u'languages', {u'customLanguage': language})
i += 1
elif myarg == u'gender':
i += 1
if checkClearBodyList(i, body, u'gender'):
i += 1
continue
gender = {}
i = getEntryType(i, gender, USER_GENDER_TYPES, customKeyword=u'other', customTypeKeyword=u'customGender')
if (i < len(sys.argv)) and (sys.argv[i].lower() == u'addressmeas'):
gender[u'addressMeAs'] = getString(i+1, u'String')
i += 2
body[u'gender'] = gender
elif myarg in [u'address', u'addresses']:
i += 1
if checkClearBodyList(i, body, u'addresses'):
@ -6846,6 +6867,16 @@ def getUserAttributes(i, cd, updateCmd=False):
else:
systemErrorExit(3, '%s is not a valid argument for user posix details. Make sure user posix details end with an endposix argument')
appendItemToBodyList(body, u'posixAccounts', posix, checkSystemId=True)
elif myarg in [u'keyword', u'keywords']:
i += 1
if checkClearBodyList(i, body, u'keywords'):
i += 1
continue
keyword = {}
i = getEntryType(i, keyword, USER_KEYWORD_TYPES, customKeyword=u'custom', customTypeKeyword=u'customType')
keyword[u'value'] = sys.argv[i]
i += 1
appendItemToBodyList(body, u'keywords', keyword)
elif myarg == u'clearschema':
if not updateCmd:
systemErrorExit(2, '%s is not a valid create user argument.' % sys.argv[i])
@ -7650,6 +7681,8 @@ def getGroupAttrValue(myarg, value, gs_object, gs_body, function):
elif params[u'type'] == u'string':
if attrib == u'description':
value = value.replace(u'\\n', u'\n')
elif attrib == u'primaryLanguage':
value = LANGUAGE_CODES_MAP.get(value.lower(), value)
elif params[u'description'].find(value.upper()) != -1: # ugly hack because API wants some values uppercased.
value = value.upper()
elif value.lower() in true_values:
@ -8683,6 +8716,15 @@ def doGetUserInfo(user_email=None):
print utils.convertUTF8(u'First Name: %s' % user[u'name'][u'givenName'])
if u'name' in user and u'familyName' in user[u'name']:
print utils.convertUTF8(u'Last Name: %s' % user[u'name'][u'familyName'])
if u'languages' in user:
up = u'languageCode'
languages = [row[up] for row in user[u'languages'] if up in row]
if languages:
print u'Languages: %s' % u','.join(languages)
up = u'customLanguage'
languages = [row[up] for row in user[u'languages'] if up in row]
if languages:
print u'Custom Languages: %s' % u','.join(languages)
if u'isAdmin' in user:
print u'Is a Super Admin: %s' % user[u'isAdmin']
if u'isDelegatedAdmin' in user:
@ -8733,6 +8775,22 @@ def doGetUserInfo(user_email=None):
else:
print utils.convertUTF8(utils.indentMultiLineText(u' value: {0}'.format(notes), n=2))
print u''
if u'gender' in user:
print u'Gender'
gender = user[u'gender']
for key in gender:
if key == u'customGender' and not gender[key]:
continue
print utils.convertUTF8(u' %s: %s' % (key, gender[key]))
print u''
if u'keywords' in user:
print u'Keywords:'
for keyword in user[u'keywords']:
for key in keyword:
if key == u'customType' and not keyword[key]:
continue
print utils.convertUTF8(u' %s: %s' % (key, keyword[key]))
print u''
if u'ims' in user:
print u'IMs:'
for im in user[u'ims']:
@ -9891,6 +9949,7 @@ USER_ARGUMENT_TO_PROPERTY_MAP = {
u'firstname': [u'name.givenName',],
u'fullname': [u'name.fullName',],
u'gal': [u'includeInGlobalAddressList',],
u'gender': [u'gender.type', u'gender.customGender', u'gender.addressMeAs',],
u'givenname': [u'name.givenName',],
u'id': [u'id',],
u'im': [u'ims',],
@ -9904,6 +9963,10 @@ USER_ARGUMENT_TO_PROPERTY_MAP = {
u'is2svenforced': [u'isEnforcedIn2Sv',],
u'is2svenrolled': [u'isEnrolledIn2Sv',],
u'ismailboxsetup': [u'isMailboxSetup',],
u'keyword': [u'keywords',],
u'keywords': [u'keywords',],
u'language': [u'languages',],
u'languages': [u'languages',],
u'lastlogintime': [u'lastLoginTime',],
u'lastname': [u'name.familyName',],
u'location': [u'locations',],

View File

@ -784,9 +784,10 @@ GAPI_MEMBERS_RETRY_REASONS = [GAPI_SYSTEM_ERROR]
USER_ADDRESS_TYPES = [u'home', u'work', u'other']
USER_EMAIL_TYPES = [u'home', u'work', u'other']
USER_EXTERNALID_TYPES = [u'account', u'customer', u'login_id', u'network',
u'organization']
USER_EXTERNALID_TYPES = [u'account', u'customer', u'login_id', u'network', u'organization']
USER_GENDER_TYPES = [u'female', u'male', u'unknown']
USER_IM_TYPES = [u'home', u'work', u'other']
USER_KEYWORD_TYPES = [u'occupation', u'outlook']
USER_LOCATION_TYPES = [u'default', u'desk']
USER_ORGANIZATION_TYPES = [u'domain_only', u'school', u'unknown', u'work']
USER_PHONE_TYPES = [u'assistant', u'callback', u'car', u'company_main',
@ -952,3 +953,28 @@ WEBCOLOR_MAP = {
u'yellow': u'#ffff00',
u'yellowgreen': u'#9acd32',
}
# Valid language codes
LANGUAGE_CODES_MAP = {
u'ach': u'ach', u'af': u'af', u'ag': u'ga', u'ak': u'ak', u'am': u'am', u'ar': u'ar', u'az': u'az', #Luo, Afrikaans, Irish, Akan, Amharic, Arabica, Azerbaijani
u'be': u'be', u'bem': u'bem', u'bg': u'bg', u'bn': u'bn', u'br': u'br', u'bs': u'bs', u'ca': u'ca', #Belarusian, Bemba, Bulgarian, Bengali, Breton, Bosnian, Catalan
u'chr': u'chr', u'ckb': u'ckb', u'co': u'co', u'crs': u'crs', u'cs': u'cs', u'cy': u'cy', u'da': u'da', #Cherokee, Kurdish (Sorani), Corsican, Seychellois Creole, Czech, Welsh, Danish
u'de': u'de', u'ee': u'ee', u'el': u'el', u'en': u'en', u'en-gb': u'en-GB', u'en-us': u'en-US', u'eo': u'eo', #German, Ewe, Greek, English, English (UK), English (US), Esperanto
u'es': u'es', u'es-419': u'es-419', u'et': u'et', u'eu': u'eu', u'fa': u'fa', u'fi': u'fi', u'fo': u'fo', #Spanish, Spanish (Latin American), Estonian, Basque, Persian, Finnish, Faroese
u'fr': u'fr', u'fr-ca': u'fr-ca', u'fy': u'fy', u'ga': u'ga', u'gaa': u'gaa', u'gd': u'gd', u'gl': u'gl', #French, French (Canada), Frisian, Irish, Ga, Scots Gaelic, Galician
u'gn': u'gn', u'gu': u'gu', u'ha': u'ha', u'haw': u'haw', u'he': u'he', u'hi': u'hi', u'hr': u'hr', #Guarani, Gujarati, Hausa, Hawaiian, Hebrew, Hindi, Croatian
u'ht': u'ht', u'hu': u'hu', u'hy': u'hy', u'ia': u'ia', u'id': u'id', u'ig': u'ig', u'in': u'in', #Haitian Creole, Hungarian, Armenian, Interlingua, Indonesian, Igbo, in
u'is': u'is', u'it': u'it', u'iw': u'iw', u'ja': u'ja', u'jw': u'jw', u'ka': u'ka', u'kg': u'kg', #Icelandic, Italian, Hebrew, Japanese, Javanese, Georgian, Kongo
u'kk': u'kk', u'km': u'km', u'kn': u'kn', u'ko': u'ko', u'kri': u'kri', u'ku': u'ku', u'ky': u'ky', #Kazakh, Khmer, Kannada, Korean, Krio (Sierra Leone), Kurdish, Kyrgyz
u'la': u'la', u'lg': u'lg', u'ln': u'ln', u'lo': u'lo', u'loz': u'loz', u'lt': u'lt', u'lua': u'lua', #Latin, Luganda, Lingala, Laothian, Lozi, Lithuanian, Tshiluba
u'lv': u'lv', u'mfe': u'mfe', u'mg': u'mg', u'mi': u'mi', u'mk': u'mk', u'ml': u'ml', u'mn': u'mn', #Latvian, Mauritian Creole, Malagasy, Maori, Macedonian, Malayalam, Mongolian
u'mo': u'mo', u'mr': u'mr', u'ms': u'ms', u'mt': u'mt', u'my': u'my', u'ne': u'ne', u'nl': u'nl', #Moldavian, Marathi, Malay, Maltese, Burmese, Nepali, Dutch
u'nn': u'nn', u'no': u'no', u'nso': u'nso', u'ny': u'ny', u'nyn': u'nyn', u'oc': u'oc', u'om': u'om', #Norwegian (Nynorsk), Norwegian, Northern Sotho, Chichewa, Runyakitara, Occitan, Oromo
u'or': u'or', u'pa': u'pa', u'pcm': u'pcm', u'pl': u'pl', u'ps': u'ps', u'pt-br': u'pt-BR', u'pt-pt': u'pt-PT', #Oriya, Punjabi, Nigerian Pidgin, Polish, Pashto, Portuguese (Brazil), Portuguese (Portugal)
u'qu': u'qu', u'rm': u'rm', u'rn': u'rn', u'ro': u'ro', u'ru': u'ru', u'rw': u'rw', u'sd': u'sd', #Quechua, Romansh, Kirundi, Romanian, Russian, Kinyarwanda, Sindhi
u'sh': u'sh', u'si': u'si', u'sk': u'sk', u'sl': u'sl', u'sn': u'sn', u'so': u'so', u'sq': u'sq', #Serbo-Croatian, Sinhalese, Slovak, Slovenian, Shona, Somali, Albanian
u'sr': u'sr', u'sr-me': u'sr-ME', u'st': u'st', u'su': u'su', u'sv': u'sv', u'sw': u'sw', u'ta': u'ta', #Serbian, Montenegrin, Sesotho, Sundanese, Swedish, Swahili, Tamil
u'te': u'te', u'tg': u'tg', u'th': u'th', u'ti': u'ti', u'tk': u'tk', u'tl': u'tl', u'tn': u'tn', #Telugu, Tajik, Thai, Tigrinya, Turkmen, Tagalog, Setswana
u'to': u'to', u'tr': u'tr', u'tt': u'tt', u'tum': u'tum', u'tw': u'tw', u'ug': u'ug', u'uk': u'uk', #Tonga, Turkish, Tatar, Tumbuka, Twi, Uighur, Ukrainian
u'ur': u'ur', u'uz': u'uz', u'vi': u'vi', u'wo': u'wo', u'xh': u'xh', u'yi': u'yi', u'yo': u'yo', #Urdu, Uzbek, Vietnamese, Wolof, Xhosa, Yiddish, Yoruba
u'zh-cn': u'zh-CN', u'zh-hk': u'zh-HK', u'zh-tw': u'zh-TW', u'zu': u'zu', #Chinese (Simplified), Chinese (Hong Kong/Traditional), Chinese (Taiwan/Traditional), Zulu
}