diff --git a/src/GamCommands.txt b/src/GamCommands.txt index 0c9b8d50..67da7f97 100644 --- a/src/GamCommands.txt +++ b/src/GamCommands.txt @@ -85,8 +85,10 @@ If an item contains spaces, it should be surrounded by ". gau|unlimited|gsuitebusiness|Google-Apps-Unlimited| gae|enterprise|gsuiteenterprise|1010020020| gsefe|e4e|gsuiteenterpriseeducation|1010310002| + gsefes|e4es|gsuiteenterpriseeducationstudent|1010310003| chrome|cdm|googlechromedevicemanagement|Google-Chrome-Device-Management| coordinate|googlecoordinate|Google-Coordinate| + d4e|driveenterprise|drive4enterprise| drive20gb|20gb|googledrivestorage20gb|Google-Drive-storage-20GB| drive50gb|50gb|googledrivestorage50gb|Google-Drive-storage-50GB| drive200gb|200gb|googledrivestorage200gb|Google-Drive-storage-200GB| @@ -353,43 +355,58 @@ If an item contains spaces, it should be surrounded by ". allowgooglecommunication| allowwebposting| archiveonly| - collaborative| + customfootertext| customreplyto| + customrolesenabledforsettingstobemerged| defaultmessagedenynotificationtext| description| directmemberscount| email| + enablecollaborativeinbox|collaborative| favoriterepliesontop| id| + includecustomfooter| includeinglobaladdresslist|gal| isarchived| maxmessagebytes| memberscanpostasthegroup| messagedisplayfont| messagemoderationlevel| - name + name| primarylanguage| replyto| sendmessagedenynotification| showingroupdirectory| spammoderationlevel| - whocanadd| whocanaddreferences| + whocanadd| + whocanapprovemessages| whocanassigntopics| + whocanassistcontent| whocancontactowner| + whocandeleteanypost| + whocandeletetopics| + whocandiscovergroup| whocanenterfreeformtags| + whocanhideabuse| whocaninvite| whocanjoin| whocanleavegroup| + whocanlocktopics| + whocanmaketopicssticky| whocanmarkduplicate| whocanmarkfavoritereplyonanytopic| whocanmarkfavoritereplyonowntopic| whocanmarknoresponseneeded| + whocanmoderatecontent| whocanmodifytagsandcategories| + whocanmovetopicsin| + whocanmovetopicsout| + whocanpostannouncements| whocanpostmessage| whocantaketopics| whocanunassigntopic| - whocanunmarkfavoritereplyonanytopic + whocanunmarkfavoritereplyonanytopic| whocanviewgroup| whocanviewmembership @@ -661,49 +678,78 @@ Specify a collection of Users by directly specifying them or by specifiying item (noreminders|(reminder email|popup|sms))| (colorindex|colorid ) - ::= + ::= (allowexternalmembers )| - (allowgooglecommunication )| (allowwebposting )| (archiveonly )| - (collaborative (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| (customfootertext )| (customreplyto )| (defaultmessagedenynotificationtext )| (description )| - (favoriterepliesontop )| - (gal|includeInGlobalAddressList )| + (enablecollaborativeinbox|collaborative )| + (includeinglobaladdresslist|gal )| (includecustomfooter )| (isarchived )| - (maxmessagebytes )| (memberscanpostasthegroup )| - (messagedisplayfont DEFAULT_FONT|FIXED_WIDTH_FONT)| - (messagemoderationlevel MODERATE_ALL_MESSAGES|MODERATE_NON_MEMBERS|MODERATE_NEW_MEMBERS|MODERATE_NONE)| + (messagemoderationlevel moderate_all_messages|moderate_non_members|moderate_new_members|moderate_none)| (name )| (primarylanguage )| - (replyto REPLY_TO_CUSTOM|REPLY_TO_SENDER|REPLY_TO_LIST|REPLY_TO_OWNER|REPLY_TO_IGNORE|REPLY_TO_MANAGERS)| + (replyto reply_to_custom|reply_to_sender|reply_to_list|reply_to_owner|reply_to_ignore|reply_to_managers)| (sendmessagedenynotification )| - (showingroupdirectory )| - (spammoderationlevel ALLOW|MODERATE|SILENTLY_MODERATE|REJECT)| - (whocanadd ALL_MEMBERS_CAN_ADD|ALL_MANAGERS_CAN_ADD|NONE_CAN_ADD)| - (whocanaddreferences (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanassigntopics (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocancontactowner ANYONE_CAN_CONTACT|ALL_IN_DOMAIN_CAN_CONTACT|ALL_MEMBERS_CAN_CONTACT|ALL_MANAGERS_CAN_CONTACT)| - (whocanenterfreeformtags (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocaninvite ALL_MEMBERS_CAN_INVITE|ALL_MANAGERS_CAN_INVITE|NONE_CAN_INVITE)| - (whocanjoin ANYONE_CAN_JOIN|ALL_IN_DOMAIN_CAN_JOIN|INVITED_CAN_JOIN|CAN_REQUEST_TO_JOIN)| - (whocanleavegroup ALL_MANAGERS_CAN_LEAVE|ALL_MEMBERS_CAN_LEAVE|NONE_CAN_LEAVE)| - (whocanmarkduplicate (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanmarkfavoritereplyonanytopic (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanmarkfavoritereplyonowntopic (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanmarknoresponseneeded (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanmodifytagsandcategories (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanpostmessage NONE_CAN_POST|ALL_MANAGERS_CAN_POST|ALL_MEMBERS_CAN_POST|ALL_IN_DOMAIN_CAN_POST|ANYONE_CAN_POST)| - (whocantaketopics (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanunassigntopic (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanunmarkfavoritereplyonanytopic (members|all_members)|(managers|owners_and_managers)|(managers_only)|(owners|owners_only)|none)| - (whocanviewgroup ANYONE_CAN_VIEW|ALL_IN_DOMAIN_CAN_VIEW|ALL_MEMBERS_CAN_VIEW|ALL_MANAGERS_CAN_VIEW)| - (whocanviewmembership ALL_IN_DOMAIN_CAN_VIEW|ALL_MEMBERS_CAN_VIEW|ALL_MANAGERS_CAN_VIEW) + (spammoderationlevel allow|moderate|silently_moderate|reject)| + (whocanadd all_members_can_add|all_managers_can_add|all_owners_can_add|none_can_add)| + (whocancontactowner anyone_can_contact|all_in_domain_can_contact|all_members_can_contact|all_managers_can_contact)| + (whocanjoin anyone_can_join|all_in_domain_can_join|invited_can_join|can_request_to_join)| + (whocanleavegroup all_members_can_leave|all_managers_can_leave|all_owners_can_leave|none_can_leave)| + (whocanpostmessage none_can_post|all_managers_can_post|all_members_can_post|all_owners_can_post|all_in_domain_can_post|anyone_can_post)| + (whocanviewgroup anyone_can_view|all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view)| + (whocanviewmembership all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view) + ::= + (whocandiscovergroup allmemberscandiscover|allindomaincandiscover|anyonecandiscover)| + (showingroupdirectory ) + ::= + (whocanassistcontent all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanassigntopics all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanenterfreeformtags all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanhideabuse all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmaketopicssticky all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmarkduplicate all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmarknoresponseneeded all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmodifytagsandcategories all_members|owners_and_managers|managers_only|owners_only|none)| + (whocantaketopics all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanunassigntopic all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanunmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none) + ::= + (whocanmoderatecontent all_members|owners_and_managers|owners_only|none)| + (whocanapprovemessages all_members|owners_and_managers|owners_only|none)| + (whocandeleteanypost all_members|owners_and_managers|owners_only|none)| + (whocandeletetopics all_members|owners_and_managers|owners_only|none)| + (whocanlocktopics all_members|owners_and_managers|owners_only|none)| + (whocanmovetopicsin all_members|owners_and_managers|owners_only|none)| + (whocanmovetopicsout all_members|owners_and_managers|owners_only|none)| + (whocanpostannouncements all_members|owners_and_managers|owners_only|none) + ::= + (whocanmoderatemembers all_members|owners_and_managers|owners_only|none)| + (whocanadd all_members_can_add|all_managers_can_add|none_can_add)| + (whocanapprovemembers all_members_can_approve|all_managers_can_approve|all_owners_can_approve|none_can_approve)| + (whocanbanusers all_members|owners_and_managers|owners_only|none)| + (whocaninvite all_members_can_invite|all_managers_can_invite|all_owners_can_invite|none_can_invite)| + (whocanmodifymembers all_members|owners_and_managers|owners_only|none) + ::= + (allowgooglecommunication )| + (favoriterepliesontop )| + (maxmessagebytes )| + (messagedisplayfont default_font|fixed_width_font)| + (whocanaddreferences all_members|owners_and_managers|managers_only|owners_only|none)| + (whocanmarkfavoritereplyonowntopic all_members|owners_and_managers|managers_only|owners_only|none) + ::= + | + | + | + | + | + ::= admin_remote_wipe|wipe|admin_account_wipe|accountwipe|wipeaccount|approve|block|cancel_remote_wipe_then_activate|cancel_remote_wipe_then_block @@ -877,9 +923,9 @@ gam update customer * gam info customer ::= - calendar| - googledrive|gdrive|drive|"drive and docs"| - gplus|googleplus|google+ + calendar| + googledrive|gdrive|drive|"drive and docs"| + gplus|googleplus|google+ ::= "(,)*" gam create datatransfer|transfer ( )* @@ -1236,7 +1282,7 @@ gam pop|pop3 [for allmail|newmail|mailfromnowon|fromn gam show pop|pop3 gam [create|add] sendas [signature|sig |(file [charset ]) (replace )*] [html] [replyto ] [default] [treatasalias ] - [smtpmsa.host smtpmsa.port 25|465|587 smtpmsa.username smtpmsa.password [smtpmsa.securitymode none|ssl|starttls]] + [smtpmsa.host smtpmsa.port 25|465|587 smtpmsa.username smtpmsa.password [smtpmsa.securitymode none|ssl|starttls]] gam update sendas [name ] [signature|sig |(file [charset ]) (replace )*] [html] [replyto ] [default] [treatasalias ] gam delete sendas gam show sendas [format] @@ -1253,15 +1299,15 @@ gam signature|sig |(file [charset ] gam show signature|sig [format] ::= - adminmanagedrestrictions| - copyrequireswriterpermission| - domainusersonly| - teammembersonly + adminmanagedrestrictions| + copyrequireswriterpermission| + domainusersonly| + teammembersonly gam create|add teamdrive gam update teamdrive [asadmin] [name ] [(theme|themeid ) | ([customtheme ] [color ])] - ( )* + ( )* gam delete teamdrive gam show teamdriveinfo [asadmin] gam show teamdrives [asadmin] diff --git a/src/gam.py b/src/gam.py index d9f0e729..0f10ef67 100755 --- a/src/gam.py +++ b/src/gam.py @@ -963,14 +963,13 @@ def callGAPIpages(service, function, items=u'items', page_token = None total_items = 0 while True: - page = callGAPI( - service, - function, - soft_errors=soft_errors, - throw_reasons=throw_reasons, - retry_reasons=retry_reasons, - pageToken=page_token, - **kwargs) + page = callGAPI(service, + function, + soft_errors=soft_errors, + throw_reasons=throw_reasons, + retry_reasons=retry_reasons, + pageToken=page_token, + **kwargs) if page: page_token = page.get(u'nextPageToken') page_items = page.get(items, []) @@ -988,10 +987,8 @@ def callGAPIpages(service, function, items=u'items', if message_attribute: first_item = page_items[0] if num_page_items > 0 else {} last_item = page_items[-1] if num_page_items > 1 else first_item - show_message = show_message.replace( - u'%%first_item%%', str(first_item.get(message_attribute, u''))) - show_message = show_message.replace( - u'%%last_item%%', str(last_item.get(message_attribute, u''))) + show_message = show_message.replace(u'%%first_item%%', str(first_item.get(message_attribute, u''))) + show_message = show_message.replace(u'%%last_item%%', str(last_item.get(message_attribute, u''))) sys.stderr.write(u'\r') sys.stderr.flush() sys.stderr.write(show_message) @@ -1024,12 +1021,11 @@ def callGAPIitems(service, function, items=u'items', Returns: The list of items in the first page of a response. """ - results = callGAPI( - service, - function, - throw_reasons=throw_reasons, - retry_reasons=retry_reasons, - **kwargs) + results = callGAPI(service, + function, + throw_reasons=throw_reasons, + retry_reasons=retry_reasons, + **kwargs) if results: return results.get(items, []) return [] @@ -8365,6 +8361,11 @@ def getGroupAttrValue(myarg, value, gs_object, gs_body, function): value = u'true' elif value.lower() in false_values: value = u'false' + # Another ugly hack because Groups Settings API doesn't have proper enumerator values set in discovery file. + if u'description' in params and params[u'description'].find(u'Possible values are: ') != -1: + possible_values = params[u'description'][params[u'description'].find(u'Possible values are: ')+21:].split(u' ') + if value not in possible_values: + systemErrorExit(2, u'value for %s must be one of %s. Got %s.' % (attrib, u', '.join(possible_values), value)) gs_body[attrib] = value return systemErrorExit(2, '%s is not a valid argument for "gam %s group"' % (myarg, function)) @@ -8372,7 +8373,7 @@ def getGroupAttrValue(myarg, value, gs_object, gs_body, function): def doCreateGroup(): cd = buildGAPIObject(u'directory') body = {u'email': normalizeEmailAddressOrUID(sys.argv[3], noUid=True)} - got_name = False + gs_get_before_update = got_name = False i = 4 gs_body = {} gs = None @@ -8396,6 +8397,9 @@ def doCreateGroup(): else: body[u'description'] = description i += 2 + elif myarg == u'getbeforeupdate': + gs_get_before_update = True + i += 1 else: if not gs: gs = buildGAPIObject(u'groupssettings') @@ -8407,12 +8411,14 @@ def doCreateGroup(): print u"Creating group %s" % body[u'email'] callGAPI(cd.groups(), u'insert', body=body, fields=u'email') if gs and not GroupIsAbuseOrPostmaster(body[u'email']): - settings = callGAPI(gs.groups(), u'get', - retry_reasons=[u'serviceLimit'], - groupUniqueId=body[u'email'], fields=u'*') - if settings is not None: - settings.update(gs_body) - callGAPI(gs.groups(), u'update', retry_reasons=[u'serviceLimit'], groupUniqueId=body[u'email'], body=settings) + if gs_get_before_update: + current_settings = callGAPI(gs.groups(), u'get', + retry_reasons=[u'serviceLimit'], + groupUniqueId=body[u'email'], fields=u'*') + if current_settings is not None: + gs_body = dict(current_settings.items() + gs_body.items()) + if gs_body: + callGAPI(gs.groups(), u'update', retry_reasons=[u'serviceLimit'], groupUniqueId=body[u'email'], body=gs_body) def doCreateAlias(): cd = buildGAPIObject(u'directory') @@ -8793,6 +8799,7 @@ def doUpdateGroup(): users_email = [normalizeEmailAddressOrUID(sys.argv[i], checkForCustomerId=True)] return (role, users_email, delivery) + gs_get_before_update = False cd = buildGAPIObject(u'directory') group = sys.argv[3] myarg = sys.argv[4].lower() @@ -8991,6 +8998,9 @@ def doUpdateGroup(): use_cd_api = True cd_body[u'adminCreated'] = getBoolean(sys.argv[i+1], myarg) i += 2 + elif myarg == u'getbeforeupdate': + gs_get_before_update = True + i += 1 else: if not gs: gs = buildGAPIObject(u'groupssettings') @@ -9002,12 +9012,14 @@ def doUpdateGroup(): group = callGAPI(cd.groups(), u'update', groupKey=group, body=cd_body, fields=u'email')[u'email'] if gs: if not GroupIsAbuseOrPostmaster(group): - settings = callGAPI(gs.groups(), u'get', - retry_reasons=[u'serviceLimit'], - groupUniqueId=group, fields=u'*') - if settings is not None: - settings.update(gs_body) - callGAPI(gs.groups(), u'update', retry_reasons=[u'serviceLimit'], groupUniqueId=group, body=settings) + if gs_get_before_update: + current_settings = callGAPI(gs.groups(), u'get', + retry_reasons=[u'serviceLimit'], + groupUniqueId=group, fields=u'*') + if current_settings is not None: + gs_body = dict(current_settings.items() + gs_body.items()) + if gs_body: + callGAPI(gs.groups(), u'update', retry_reasons=[u'serviceLimit'], groupUniqueId=group, body=gs_body) print u'updated group %s' % group def doUpdateAlias(): @@ -10878,7 +10890,7 @@ def doPrintShowAlerts(): titles.append(field) csv_rows.append(aj) writeCSVfile(csv_rows, titles, u'Alerts', False) - + def doPrintShowAlertFeedback(): _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth(u'email')) feedback = callGAPIpages(ac.alerts().feedback(), u'list', u'feedback', alertId=u'-') @@ -10886,7 +10898,7 @@ def doPrintShowAlertFeedback(): print feedbac def _getValidAlertFeedbackTypes(ac): - return [type for type in ac._rootDesc[u'schemas'][u'AlertFeedback'][u'properties'][u'type'][u'enum'] if type != u'ALERT_FEEDBACK_TYPE_UNSPECIFIED'] + return [aftype for aftype in ac._rootDesc[u'schemas'][u'AlertFeedback'][u'properties'][u'type'][u'enum'] if aftype != u'ALERT_FEEDBACK_TYPE_UNSPECIFIED'] def doCreateAlertFeedback(): _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth(u'email')) @@ -13582,9 +13594,9 @@ def ProcessGAMCommand(args): systemErrorExit(2, '%s is not a valid argument for "gam watch"' % watchWhat) else: systemErrorExit(2, '%s is not a valid argument for "gam"' % command) - except IndexError: - showUsage() - sys.exit(2) + #except IndexError: + # showUsage() + # sys.exit(2) except KeyboardInterrupt: sys.exit(50) except socket.error as e: diff --git a/src/var.py b/src/var.py index c5f2f0b9..05f74c79 100644 --- a/src/var.py +++ b/src/var.py @@ -52,7 +52,7 @@ SKUS = { u'1010310002': { u'product': u'101031', u'aliases': [u'gsefe', u'e4e', u'gsuiteenterpriseeducation'], u'displayName': u'G Suite Enterprise for Education'}, u'1010310003': { - u'product': u'101031', u'aliases': [u'gse4es', u'e4es', u'gsuiteenterpriseeducationstudent'], u'displayName': u'G Suite Enterprise for Education Student'}, + u'product': u'101031', u'aliases': [u'gsefes', u'e4es', u'gsuiteenterpriseeducationstudent'], u'displayName': u'G Suite Enterprise for Education Student'}, u'Google-Apps': { u'product': u'Google-Apps', u'aliases': [u'standard', u'free'], u'displayName': u'G Suite Free/Standard'}, u'Google-Apps-For-Business': {