Uploaded image for project: 'Jira Service Management Data Center'
  1. Jira Service Management Data Center
  2. JSDSERVER-15647

Groovy script is not triggered via Assets Automation when groovy file name has dashes in it

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Medium Medium
    • 10.1.2
    • 5.12.14
    • Assets - Automation

      Issue Summary

      Groovy script is not triggered via Assets Automation after upgrading JSM version to 5.12.14.

      Steps to Reproduce

      • Create the following automation in a scheme (the rule must be triggered by the current user)
        • When - Object Updated
        • If - Any objects
        • Then -
          • Action - Execute Groovy script
          • File path - D:/Atlassian/Application Data/JIRA/scripts/Insight/insight-restore-attribute-value.groovy
            Use the following code in the script
      /*
       This script checks if changes were made by user who is able to edit specific attribute in Inisght.
       It protects from adding the wrong people as approvers in Release process.
       Updated PTC-4925:
       The script checks an update on Security approvers attribute and restore the previous value if the update was made by
       user that's not a schema manager.
       */
      import com.atlassian.jira.component.ComponentAccessor
      import com.atlassian.jira.security.groups.GroupManager
      import com.atlassian.jira.user.ApplicationUser
      import com.riadalabs.jira.plugins.insight.services.model.CommentBean
      import com.riadalabs.jira.plugins.insight.services.model.RoleBean
      import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
      import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeFacade
      import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ConfigureFacade
      
      interface scriptConfig {
          final GroupManager groupManager = ComponentAccessor.getGroupManager()
          final ApplicationUser svcScriptRunner = ComponentAccessor.getUserManager().getUserByName("svc.JIRA.ScriptRunne") // Service account
          final String firstApproverAttribute = "Domain Owner - First Approver" // First Approver attribute name
          final String approvalDelegateAttribute = "Domain - Release First Approval Delegate" // Release First Approval Delegate attribute name
          final String secApproversAttribute = "Security approvers" // Release First Approval Delegate attribute name
          final int domainDelegatesAttributeID = 479 // Id of Domain Delegates attribute which triggers the script
          final int securityApproversAttributeId = 866 // Id of Security Approvers attribute which triggers the script
          final String jiraAdminsGroup = "jira-administrators" // Name of group for Jira Admins
          final Integer commentRole = 0 // The ID of the role for which the comment is visible, 0 means comment is public
          final ObjectFacade objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
          final ObjectTypeFacade objectTypeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeFacade)
          final ConfigureFacade configureFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ConfigureFacade)
          final int orgSchemeId = 1
          final String managerSchemeRole = "Object Schema Managers"
          final String userRoleType = "atlassian-user-role-actor"
          final String groupRoleType= "atlassian-group-role-actor"
      }
      log.warn("Attribute restore START")
      main()
      log.warn("Attribute restore END")
      /*
       This main function returns old value in attribute if was edited by wrong person.
       */
      void main(){
          try {
      		log.warn("objectUpdateList ${objectUpdateList}")
      		log.warn("objectUpdateList available properties ${objectUpdateList.getProperties()}")
              objectUpdateList.each{ change ->
      
                  if (change.getAttributeName() == scriptConfig.approvalDelegateAttribute){
                      restoreDomainDelegatesValue(change)
                  } else if (change.getAttributeName() == scriptConfig.secApproversAttribute){
                      restoreSecurityApprovers(change)
                  }
              }
          }catch(Exception e){
              log.warn(e.toString())
              log.warn(e.stackTrace.toString())
          }
      
      }
      
      /**
       *  Restores a previous value of the Domain Owner - First Approver attribute if it was updated by user that is not allowed to do it.
       * @param change
       */
      void restoreDomainDelegatesValue(def change){
          ApplicationUser user = ComponentAccessor.getUserManager().getUserByName(currentUser.getName())
          log.warn(ComponentAccessor.getGroupManager().isUserInGroup(user, scriptConfig.jiraAdminsGroup).toString())
          log.warn(isUserInJiraAdminGroup(user))
      
          def isUserInJiraAdminGroup = isUserInJiraAdminGroup(user)
          boolean isUserDomainOwner = isUserDomainOwner(object,scriptConfig.firstApproverAttribute,user)
          boolean isUserSvcAccount = isUserSvcAccount(user)
          String message = "Dear $user.displayName, you are not allowed to edit ${scriptConfig.approvalDelegateAttribute} attribute." +
                  "Please contact with ${scriptConfig.firstApproverAttribute} or Jira Admins."
      
          if (!isUserDomainOwner && !isUserSvcAccount && !isUserInJiraAdminGroup){
              addCommentToObject(message,scriptConfig.svcScriptRunner,object,scriptConfig.commentRole)
              ArrayList<String> oldValue = change.getRemovedValues() as ArrayList
              updateAttributeInObject(object, oldValue, scriptConfig.domainDelegatesAttributeID)
          } else {
              log.warn("User changed ${change.getAttributeName()}")
          }
      }
      
      /**
       * Restores a previous value of the Security Approvers attribute if it was updated by user that is not allowed to do it.
       * @param change
       */
      void restoreSecurityApprovers(def change){
          ApplicationUser currentUser = currentUser as ApplicationUser
          boolean isUserInJiraAdminGroup = isUserInJiraAdminGroup(currentUser)
          boolean isUserSvcAccount = isUserSvcAccount(currentUser)
          boolean isUserSchemeManager = isUserMemberOfRole(currentUser, scriptConfig.managerSchemeRole)
          String message = "Dear $currentUser.displayName, you are not allowed to edit ${scriptConfig.secApproversAttribute} attribute." +
                  "Please contact with scheme managers or Jira Admins."
          if (!isUserInJiraAdminGroup && !isUserSvcAccount  && !isUserSchemeManager){
              addCommentToObject(message,scriptConfig.svcScriptRunner,object,scriptConfig.commentRole)
              ArrayList<String> oldValue = change.getRemovedValues() as ArrayList
              updateAttributeInObject(object, oldValue, scriptConfig.securityApproversAttributeId)
          } else {
              log.warn("User changed ${change.getAttributeName()}")
          }
      }
      
      /**
       *
       * @param currentUser - User that made a change on an object
       * @param roleName - A roleName where the user must be added to return TRUE
       * @return TRUE / FALSE depends if the user is a particular group
       */
      boolean isUserMemberOfRole(ApplicationUser currentUser, String roleName){
          List<String> usersInRole = []
          List<RoleBean> roles = scriptConfig.configureFacade.findRoleBeansByObjectSchema(scriptConfig.orgSchemeId)
      
          roles.each{ role ->
      
              if (role.name == roleName){
                  role.roleActorBeans.each{roleActorBean ->
      
                      if (roleActorBean.type == scriptConfig.groupRoleType){
                          usersInRole += scriptConfig.groupManager.getUsersInGroup(roleActorBean.typeParameter).key
      
                      } else if (roleActorBean.type == scriptConfig.userRoleType){
                          usersInRole += roleActorBean.typeParameter
                      }
                  }
              }
          }
          return currentUser.key in usersInRole
      }
      
      /**
       *  This function checks whether the user who edited the attribute is the owner of the object.
       https://documentation.mindville.com/display/INSSERV/Update+object+attribute
       * @param domainObject - An object that was updated
       * @param attributeName - A name of the attribute
       * @param currentUser - A user that
       * @return
       */
      boolean isUserDomainOwner(def domainObject, String attributeName, ApplicationUser currentUser){
          Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().
                  findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade")
          def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass)
          def attributeBean = objectFacade.loadObjectAttributeBean(domainObject.getId(), attributeName)
          ArrayList<String> owners = []
      
          if (attributeBean != null) {
              attributeValue = attributeBean.getObjectAttributeValueBeans()
      
              attributeValue.each{user ->
                  owners += user.getValue().toLowerCase()
              }
          }
      
          if (owners.size() > 0){
              log.warn("${object} is owned by ${owners}.")
              log.warn("Is ${currentUser.displayName} the Domain owner? ${owners.contains(currentUser.username.toLowerCase())}")
              return owners.contains(currentUser.key.toLowerCase())
          }
      }
      
      /**
       * This function checks whether the user who edited the attribute is the Jira admin.
       * @param currentUser - user that triggered a change
       * @return TRUE/FALSE
       */
      def isUserInJiraAdminGroup(ApplicationUser currentUser){
          log.warn(currentUser)
          try{
              log.warn(currentUser)
              return ComponentAccessor.getGroupManager().isUserInGroup(currentUser, scriptConfig.jiraAdminsGroup)
          } catch (Exception e){
              log.warn(e.toString())
              log.warn(e.stackTrace.toString())
          }
      
      }
      
      /**
       * This function checks whether the user who edited the attribute is the svc account.
       * @param currentUser 0 user that triggered a change
       * @return
       */
      boolean isUserSvcAccount (ApplicationUser currentUser){
          return currentUser.username.toLowerCase() == scriptConfig.svcScriptRunner.username.toLowerCase()
      }
      
      /**
       * This function restores previous value in edited attribute.
       * @param insightObject - An object that was updated
       * @param oldValue - Old value of the object attribute
       * @param attributeId - An id of the attribute
       */
      void updateAttributeInObject(def insightObject, ArrayList<String> oldValue, Integer attributeId){
          // Set svc account ass current user
          ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(scriptConfig.svcScriptRunner)
      
          // Get Insight Object Facade from plugin accessor
          Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader()
                  .findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade")
          def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass)
          def newObjectAttributeBean
      
          // Get Insight Object Attribute Facade from plugin accessor
          Class objectTypeAttributeFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader()
                  .findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade")
          def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectTypeAttributeFacadeClass)
      
          // Get the factory that creates Insight Attributes
          Class objectAttributeBeanFactoryClass = ComponentAccessor.getPluginAccessor().getClassLoader()
                  .findClass("com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory")
          def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(objectAttributeBeanFactoryClass)
      
          // This is the user object type attribute and the one we want to modify
          def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(attributeId)
          def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.getId(), objectTypeAttributeBean.getId())
      
          // If old value is empty, script sets null in attribute value
          if(oldValue.size() > 0){
              newObjectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, *oldValue)
              //  Reuse the old id for the new attribute
              newObjectAttributeBean.setId(objectAttributeBean.getId())
              // Store the object attribute into Insight.
              objectAttributeBean = objectFacade.storeObjectAttributeBean(newObjectAttributeBean)
          } else {
              // Clear attribute value
              objectAttributeBean = objectFacade.deleteObjectAttributeBean(objectAttributeBean.getId().longValue())
          }
      }
      
      /**
       *  This function adds comment if user is not allowed to edit attribute.
       * @param message - A message that is added as a comment
       * @param commentAuthor - An author of the comment
       * @param insightObject - An object where the comment is added
       * @param schemeRole - A role which can see the comment
       */
      void addCommentToObject(String message, ApplicationUser commentAuthor, def insightObject, int schemeRole){
          ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(scriptConfig.svcScriptRunner)
      
          Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader()
                  .findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade")
          def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass)
          CommentBean commentBean = new CommentBean()
          commentBean.setComment(message)
          commentBean.setRole(schemeRole)
          commentBean.setAuthor(commentAuthor.getKey())
          commentBean.setObjectId(insightObject.getId())
          objectFacade.storeCommentBean(commentBean)
      }
      • Edit any object

      Expected Results

      • A value of the attribute should be restored if the script was triggered by a user who is not allowed to edit it.
      • The following comment should be added to the object
        Dear <CURRENT_USER_DISPLAY_NAME> you are not allowed to edit Domain - Release First Approval Delegate attribute. Please contact with Domain Owner - First Approver or Jira Admins.

      Actual Results

      The script fails on line 71 without any errors logged to the log file.

      Workaround

      Change the name of groovy script to follow Java class name restriction, excluding '-' or any illegal characters for a Java class name. 

      This issue should not exist in JSM 10.x 

              4efd9de64ab4 Mingyi Yang
              nravi@atlassian.com Naveen Ravi
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: