def create(ticket_data): """ Ticket creation handler. """ cf_email_address = custom_fields.get("Email Address") email_address = shared_sd.get_field(ticket_data, cf_email_address) if email_address is None: # It shouldn't be - it is a mandatory field ... shared_sd.post_comment( "It has not been possible to create the account as requested.", True) shared_sd.post_comment( "Unable to retrieve email address from CF %s" % cf_email_address, False) shared_sd.resolve_ticket("Declined") return email_address = email_address.strip().lower() email_address = shared_ldap.cleanup_if_gmail(email_address) shared_sd.set_summary("Create external user/account for %s" % email_address) if not ok_to_proceed(email_address): return cf_first_name = custom_fields.get("First Name") cf_family_name = custom_fields.get("Family Name") first_name = shared_sd.get_field(ticket_data, cf_first_name) if first_name is not None: first_name = first_name.strip() surname = shared_sd.get_field(ticket_data, cf_family_name).strip() uid = shared_ldap.calculate_uid(first_name, surname) if uid is None: shared_sd.post_comment( "It has not been possible to create the account as requested.", True) shared_sd.post_comment( "Cannot calculated UID for '%s' '%s'" % (first_name, surname), False) shared_sd.resolve_ticket("Declined") return md5_password = None cf_account_type = custom_fields.get("External Account / Contact") account_type = shared_sd.get_field(ticket_data, cf_account_type) if account_type != "Contact": _, md5_password = linaro_shared.make_password() account_dn = shared_ldap.create_account(first_name, surname, email_address, md5_password) if account_dn is None: shared_sd.post_comment( "Sorry but something went wrong while creating the entry", True) shared_sd.transition_request_to("Waiting for support") shared_sd.assign_issue_to(None) return if account_type != "Contact": send_new_account_email(first_name, surname, email_address, account_dn) shared_sd.resolve_ticket()
def process_public_comment(ticket_data, last_comment, keyword): """ Logic to process a public comment """ shared_sd.assign_issue_to(shared.globals.CONFIGURATION["bot_name"]) # If the original reporter IS a group owner, we will only accept comments # from the same person and those comments will be add/remove commands. # # Otherwise, deassign and let IT work on what was said. _, result = get_group_details(ticket_data) # Make sure that the group still exists because this is all asynchronous # and anything could have happened! if not group_sanity_check(result): return True if ("owner" in result[0] and shared_ldap.reporter_is_group_owner(result[0].owner.values) and keyword in ("add", "remove")): distinguished = result[0].entry_dn grp_name = shared_ldap.extract_id_from_dn(distinguished) changes = last_comment["body"].split("\n") batch_process_membership_changes(grp_name, changes, False) return True return False
def create(ticket_data): """ Create handler. """ # There aren't any fields in the form for us to process. This # is a simple case of checking that the requestor is a member of # staff and then adding them to the group that controls SSH access # to the system. email_address = shared_sd.reporter_email_address(ticket_data) account_dn = shared_ldap.find_from_email(email_address) valid_account = shared_ldap.is_dn_in_group("employees", account_dn) or \ shared_ldap.is_dn_in_group("assignees", account_dn) if not valid_account: shared_sd.post_comment( "You must be a Linaro employee or assignee to use the " "hackbox2 service.", True) shared_sd.resolve_ticket(resolution_state="Won't Do") return if shared_ldap.is_dn_in_group("hackbox-users", account_dn): shared_sd.post_comment( "You appear to already have access.", True) shared_sd.resolve_ticket() return if shared_ldap.add_to_group("hackbox-users", account_dn): shared_sd.post_comment( "Access has been granted. Please ensure you read " "https://collaborate.linaro.org/display/IKB/Hackbox2 " "and associated documentation so that you fully understand " "what this service is, how to use it and what the limitations " "are.", True) shared_sd.resolve_ticket() else: shared_sd.post_comment( "A problem occurred while adding you to the permission list. " "It will be necessary to get IT Services to investigate.", True) # Deassign the ticket shared_sd.assign_issue_to(None) shared_sd.transition_request_to("Waiting for Support")
def create(ticket_data): """ Triggered when the issue is created """ cf_approvers = custom_fields.get("Approvers") group_email_address, result = get_group_details(ticket_data) shared_sd.set_summary("Add/Remove group members for %s" % group_email_address) shared_sd.assign_issue_to(shared.globals.CONFIGURATION["bot_name"]) if not group_sanity_check(result): return group_obj = result[0] if "owner" not in group_obj: if shared_ldap.is_user_in_group("its", shared.globals.REPORTER): shared_sd.transition_request_to("In progress") return shared_sd.post_comment( "This group has no owners. Asking IT Services to review your" " request.", True) it_members = shared_ldap.get_group_membership( "cn=its,ou=mailing,ou=groups,dc=linaro,dc=org") shared_sd.assign_approvers(it_members, cf_approvers) return if IT_BOT in group_obj.owner.values: shared_sd.post_comment( "Sorry but the membership of this group is maintained" " automatically.", True) shared_sd.resolve_ticket(WONT_DO) return if shared_ldap.reporter_is_group_owner(group_obj.owner.values): shared_sd.transition_request_to("In progress") return shared_sd.post_comment( "As you are not an owner of this group, the owners will be asked" " to approve or decline your request.", True) shared_sd.assign_approvers(group_obj.owner.values, cf_approvers)
def process_public_comment(ticket_data, last_comment, keyword): """Logic to process a public comment.""" shared_sd.assign_issue_to(shared.globals.CONFIGURATION["bot_name"]) # If the original reporter IS a group owner, we will only accept comments # from the same person and those comments will be add/remove commands. # # Otherwise, deassign and let IT work on what was said. # # Get the definitive email address for the group and the owner(s). cf_group_email_address = custom_fields.get(GROUP_EMAIL_ADDRESS) group_email_address = shared_sd.get_field( ticket_data, cf_group_email_address).strip().lower() group_email_address, result = shared_ldap.find_group( group_email_address, ['owner']) # Make sure that the group still exists because this is all asynchronous # and anything could have happened! if len(result) == 0: shared_sd.post_comment( "Sorry but the group's email address can't be found in Linaro " "Login.", True) shared_sd.resolve_ticket(WONT_DO) return True if len(result) != 1: shared_sd.post_comment( "Sorry but, somehow, the group's email address appears more than " "once in Linaro Login.", True) shared_sd.resolve_ticket(WONT_DO) return True if (result[0].owner.values != [] and shared_ldap.reporter_is_group_owner(result[0].owner.values) and keyword in ("add", "remove")): grp_name = shared_ldap.extract_id_from_dn(result[0].entry_dn) changes = last_comment["body"].split("\n") batch_process_ownership_changes(grp_name, changes) post_owners_of_group_as_comment(result[0].entry_dn) return True return False
def create(ticket_data): """ Triggered when the issue is created """ shared_sd.assign_issue_to(shared.globals.CONFIGURATION["bot_name"]) # Keep the linter happy _ = ticket_data # Need to get all of the groups, with their owners all_groups = shared_ldap.find_matching_objects( "(objectClass=groupOfUniqueNames)", ["owner", "displayName", "cn", "uniqueMember"] ) owned_groups = [] for group in all_groups: owners = group.owner.values if shared_ldap.reporter_is_group_owner(owners): owned_groups.append(group) if owned_groups == []: shared_sd.post_comment( "You do not appear to be the owner of any " "groups on Linaro Login.", True ) shared_sd.resolve_ticket() return owned_groups = sorted(owned_groups, key=group_name_lower) response = ( "Below are the groups you can manage.\n\n" "There are automated Service Desk requests for [changing the " "membership of a group|https://servicedesk.linaro.org/servicedesk" "/customer/portal/3/create/139] and [changing the owners of a " "group|https://servicedesk.linaro.org/servicedesk/customer/portal" "/3/create/140].\n\n" ) for group in owned_groups: empty = check_if_group_has_members(group) response += "* %s%s\n" % (group_name(group), empty) shared_sd.post_comment(response, True) shared_sd.resolve_ticket()
def create(ticket_data): """ Create handler. """ # Start by making sure that the requester is in IT or HR. email_address = shared_sd.reporter_email_address(ticket_data) account_dn = shared_ldap.find_from_email(email_address) valid_account = shared_ldap.is_dn_in_group("hr", account_dn) or \ shared_ldap.is_dn_in_group("it-services", account_dn) if not valid_account: shared_sd.post_comment( "You must be in HR or IT Services to use this request.", True) shared_sd.resolve_ticket(resolution_state="Won't Do") return outcome = RESULT_STATE.Done cf_addresses = custom_fields.get("Email Address(s) of Users") addresses = shared_sd.get_field(ticket_data, cf_addresses).split("\r\n") for address in addresses: # Clean up by trimming white space. clean = address.strip().lower() if clean != "": result = transition_user_account(clean) if (result == RESULT_STATE.IT or (result == RESULT_STATE.Customer and outcome == RESULT_STATE.Done)): outcome = result # Did all of the accounts transition? if outcome == RESULT_STATE.Done: shared_sd.resolve_ticket() elif outcome == RESULT_STATE.Customer: shared_sd.post_comment( "Sorry but it has not been possible to fully process your request. " "Hopefully the above comments are helpful. Further replies to this " "ticket will be handled by IT Services staff rather than the automation bot.", True) shared_sd.assign_issue_to(None) else: shared_sd.transition_request_to("Waiting for Support")
def create(ticket_data): """Triggered when the issue is created.""" cf_group_email_address = custom_fields.get(GROUP_EMAIL_ADDRESS) group_email_address = shared_sd.get_field( ticket_data, cf_group_email_address).strip().lower() group_email_address, result = shared_ldap.find_group( group_email_address, ['owner']) shared_sd.set_summary( "View/Change group ownership for %s" % group_email_address) shared_sd.assign_issue_to(shared.globals.CONFIGURATION["bot_name"]) if len(result) == 0: shared_sd.post_comment( "Sorry but the group's email address can't be found in Linaro " "Login.", True) shared_sd.resolve_ticket(WONT_DO) return if len(result) != 1: shared_sd.post_comment( "Sorry but, somehow, the group's email address appears more than " "once in Linaro Login.", True) shared_sd.resolve_ticket(WONT_DO) return # See if the bot owns this group owners = result[0].owner.values if (len(owners) == 1 and owners[0] == IT_BOT): shared_sd.post_comment( ( "This group is maintained through automation. It is not " "possible to change the owners of this group or raise " "tickets to directly change the membership. If you want " "to understand how this group is maintained automatically, " "please raise a general IT Services support ticket." ), True ) shared_sd.resolve_ticket() return # Do we have any changes to process? If not, post the current owners to # the ticket. cf_group_owners = custom_fields.get("Group Owners") ownerchanges = shared_sd.get_field(ticket_data, cf_group_owners) if ownerchanges is None: post_owners_of_group_as_comment(result[0].entry_dn) if shared_ldap.reporter_is_group_owner(result[0].owner.values): shared_sd.post_comment( ("As you are an owner of this group, you can make changes to " "the ownership by posting new comments to this ticket with " "the following format:\r\n" "*add* <email address>\r\n" "*remove* <email address>\r\n" "One command per line but you can have multiple changes in a " "single comment. If you do not get the syntax right, the " "automation will not be able to understand your request and " "processing will stop.\r\n"), True) shared_sd.transition_request_to("Waiting for customer") else: shared_sd.post_comment( "As you are not an owner of this group, if you want to make " "changes to the ownership, you will need to open a " "[new ticket|https://servicedesk.linaro.org/servicedesk/" "customer/portal/3/create/140].", True) shared_sd.resolve_ticket() return # There are changes ... but is the requester a group owner? cf_approvers = custom_fields.get("Approvers") if result[0].owner.values == []: # No owners at all. IT is always allowed to make changes if shared_ldap.is_user_in_group("its", shared.globals.REPORTER): shared_sd.transition_request_to("In progress") else: shared_sd.post_comment( "This group has no owners. Asking IT Services to review " "your request.", True) it_members = shared_ldap.get_group_membership( "cn=its,ou=mailing,ou=groups,dc=linaro,dc=org") shared_sd.assign_approvers(it_members, cf_approvers) shared_sd.transition_request_to("Needs approval") elif shared_ldap.reporter_is_group_owner(result[0].owner.values): shared_sd.transition_request_to("In progress") else: shared_sd.post_comment( "As you are not an owner of this group, the owners will be " "asked to approve or decline your request.", True) shared_sd.assign_approvers(result[0].owner.values, cf_approvers) shared_sd.transition_request_to("Needs approval")