How to display error message from progressErrorCollection.getErrors().toString() in Jira screen, scriptrunner postfunction - jira

I have an error message that is thrown when I try to execute a postfunction, the error message is: 
org.ofbiz.core.entity.GenericTransactionException: Commit failed, rollback previously requested by nested transaction.
You can see the error message in this screenshot:
In my code, I am using the line : 
        log.warn("MOUNA here 2 "+progressErrorCollection.getErrors().toString()) which is displaying a more meaninful message to the user which is: fixVersions:Fix Version/s is required. I would like to print this message instead to the user instead of org.ofbiz.core.entity.GenericTransactionException: Commit failed, rollback previously requested by nested transaction.
How can I enforce this? I have tried using 
      UserMessageUtil.error(progressErrorCollection.getErrors().toString()) but it is not working. Anyone knows? Here is my code below: 
package CombineTransitions
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.issue.Issue;
import org.apache.log4j.Logger
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.Issue;
import CombineTransitions.Configuration_CombineTransitions
import com.atlassian.jira.bc.issue.IssueService.IssueResult
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult
import com.atlassian.jira.event.type.EventDispatchOption
import  java.util.concurrent.TimeUnit
import  java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.Executors
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.opensymphony.workflow.WorkflowContext;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.util.ErrorCollection
import com.atlassian.jira.workflow.WorkflowException
def log1 = Logger.getLogger("atlassian-jira.log")
def combineTransitionsHashMap= Configuration_CombineTransitions.getCombineTransitionsHashMap()
def issueStatusTypeId = combineTransitionsHashMap["issueStatusTypeId"] as String;
def transitionFromOpentoFixed = combineTransitionsHashMap["transitionFromOpentoFixed"] as Integer;
def transitionFromFixedToTested = combineTransitionsHashMap["transitionFromFixedToTested"] as Integer;
def transitionFromTestedToCompleted = combineTransitionsHashMap["transitionFromTestedToCompleted"] as Integer;
def fixedStatusName = combineTransitionsHashMap["fixedStatusName"] as String;
def testedStatusName = combineTransitionsHashMap["testedStatusName"] as String;
def completedStatusName = combineTransitionsHashMap["completedStatusName"] as String;
def fixedStatusId = combineTransitionsHashMap["fixedStatusId"] as String;
def testedStatusId = combineTransitionsHashMap["testedStatusId"] as String;
def completedStatusId = combineTransitionsHashMap["completedStatusId"] as String;
if (issue.getStatus().getSimpleStatus().getId().equals(issueStatusTypeId)) {
        def ok = false
         ok=performTransition(transitionFromOpentoFixed, fixedStatusName, fixedStatusId);
         log.warn("MOUNA first boolean "+ok +" "+fixedStatusName)
   if(ok){
         ok= performTransition(transitionFromFixedToTested, testedStatusName, testedStatusId);
         log.warn("MOUNA second boolean "+ok +" "+testedStatusName)
         if(ok){
          ok= performTransition(transitionFromTestedToCompleted, completedStatusName, completedStatusId);
          log.warn("MOUNA third boolean "+ok +" "+completedStatusName)
         }
 
  }
   
   
}
def  performTransition(int transitionToBeDone, String destinationStatus, String statusId ) {
  log.warn("MOUNA  ORIGINAL STATUS "+ issue.getStatus()  + "DEST STATUS "+ destinationStatus)
issue = ComponentAccessor.getIssueManager().getIssueObject(issue.id)
  def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
 
  String issueKey = issue.getKey()
  IssueService issueService = ComponentAccessor.getIssueService()
  def issueInputParameters = issueService.newIssueInputParameters()
  issueInputParameters.setComment("Transitioning issue from status "+ issue.getStatus().getName()+" to status "+ destinationStatus );
WorkflowTransitionUtil workflowTransitionUtil = (WorkflowTransitionUtil) JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class)
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setAction(transitionToBeDone)
ErrorCollection errorCollection=workflowTransitionUtil.validate()
if (errorCollection.hasAnyErrors()) {
    log.warn("MOUNA here 1 "+errorCollection.getErrorMessages().toString())
return false;
}else{
 
    ErrorCollection progressErrorCollection=workflowTransitionUtil.progress()
    if(progressErrorCollection.hasAnyErrors()){
        log.warn("MOUNA here 2 "+progressErrorCollection.getErrors().toString())
            //  throw new WorkflowException(progressErrorCollection.getErrors().toString());
      UserMessageUtil.error(progressErrorCollection.getErrors().toString())
   
          return false;
    }else{
      return true;
    }
}
 
 
}

Related

Sim7020 not connecting with AT+CHTTPCON=0

I’m trying to connect to a webpage link using a Waveshare Sim7020 module through a Raspberry Pico, using https AT commands, but the connect command returns an error.
My final objective is to send a telegram message from it using a bot link for it like explained in https://core.telegram.org/bots/api#making-requests using this method:
https://api.telegram.org/bot\<token>/METHOD_NAME
This is not working for me, so thinking that maybe this is complex I’m trying to connect to google, bur the problem continues. I have also syncronized the time on the module with a server. I’m wondering that it could be a certificate problem? These are the functions used:
from machine import Pin, ADC 
import os
import utime
import binascii
#import ujson
#print sys info
print(os.uname())
#using pin defined
ADC0= ADC(Pin(26))
sensor_temp = ADC(4)
led_pin =25  #onboard led
pwr_en = 14  #pin to control the power of sim7020x
uart_port = 0
uart_baute = 115200
APN = "cmnbiot"
i=0
reading=0
temperature=0
#indicate program started visually
led_onboard = machine.Pin(led_pin, machine.Pin.OUT)
def led_blink():
    led_onboard.value(1)
    utime.sleep(0.5)
    led_onboard.value(0)
    utime.sleep(0.5)
    led_onboard.value(1)
    utime.sleep(0.5)
    led_onboard.value(0)
def hexStr_to_str(hex_str):
    hex = hex_str.encode('utf-8')
    str_bin = binascii.unhexlify(hex)
    return str_bin.decode('utf-8')
def str_to_hexStr(string):
    str_bin = string.encode('utf-8')
    return binascii.hexlify(str_bin).decode('utf-8')
#power on the sim800c
def powerOn(pwr_en):
    pwr_key = machine.Pin(pwr_en, machine.Pin.OUT)
    pwr_key.value(1)
#power down the sim800c
def powerDown(pwr_en):
    pwr_key = machine.Pin(pwr_en, machine.Pin.OUT)
    pwr_key.value(0)
#2 sec timeout is arbitrarily chosen
def sendCMD_waitResp(cmd, timeout=2000):
    print("CMD: " + cmd)
    uart.write((cmd+'\r\n').encode())
    waitResp(timeout)
    print()
    
def waitResp(timeout=2000):
    prvMills = utime.ticks_ms()
    resp = b""
    while (utime.ticks_ms()-prvMills)<timeout:
        if uart.any():
            resp = b"".join([resp, uart.read(1)])
    print((resp).decode())
def sendCMD_waitRespLine(cmd, timeout=2000):
    print("CMD: " + cmd)
    uart.write((cmd+'\r\n').encode())
    waitRespLine(timeout)
    print()
    
def waitRespLine(timeout=2000):
    prvMills = utime.ticks_ms()
    while (utime.ticks_ms()-prvMills)<timeout:
        if uart.any():
            print((uart.readline()).decode())
            
#APN Manual configuration
def apnConfig(APN):
    sendCMD_waitResp("AT+CFUN=0")        #Disable RF
    sendCMD_waitResp("AT*MCGDEFCONT=\"IP\",\""+ APN +"\"")        #Set the APN manually
    sendCMD_waitResp("AT+CFUN=1")        #Enable RF
    utime.sleep(1)
    sendCMD_waitResp("AT+CGATT?")        #Inquiry PS service
    sendCMD_waitResp("AT+CGREG?")
    sendCMD_waitResp("AT+CGCONTRDP")      #Attached PS domain and got IP address automatically
Then this are the AT command tests and APN configuration:
#print uart info
uart = machine.UART(uart_port, uart_baute, bits=8, parity=None, stop=1)
print(uart)
#power on the board
powerOn(pwr_en)
#clear bufer in UART
waitResp()
#AT commands test
atCommandTest()
#APN Manual configuration
apnConfig(APN)
Then this is the time syncronization:
sendCMD_waitResp("AT+CSNTPSTART=\"[ntp.i2t.ehu.es](http://ntp.i2t.ehu.es/)\"")
sendCMD_waitResp("AT+CCLK?")
sendCMD_waitResp("AT+CSNTPSTOP")
sendCMD_waitResp("AT+CSNTPSTART=\"[ntp.i2t.ehu.es](http://ntp.i2t.ehu.es/)\",\"+01\"")
sendCMD_waitResp("AT+CCLK?")
sendCMD_waitResp("AT+CSNTPSTOP")
sendCMD_waitResp("AT+CURTC=1")
sendCMD_waitResp("AT+CRESET")
sendCMD_waitResp("AT+CURTC?")
sendCMD_waitResp("AT+CSNTPSTART=\"[ntp.i2t.ehu.es](http://ntp.i2t.ehu.es/)\"")
sendCMD_waitResp("AT+CCLK?")
sendCMD_waitResp("AT+CSNTPSTOP")
sendCMD_waitResp("AT+CURTC=1")
sendCMD_waitResp("AT+CURTC?")
sendCMD_waitResp("AT+CSNTPSTART=\"[ntp.i2t.ehu.es](http://ntp.i2t.ehu.es/)\",\"+01\"")
sendCMD_waitResp("AT+CCLK?")
sendCMD_waitResp("AT+CSNTPSTOP")
And this is the connection try out, where on create says OK but on connect says “ERROR”:
sendCMD_waitResp("AT+CHTTPCREATE=\"https://www.google.com/\"") 
sendCMD_waitResp("AT+CHTTPCON=0")    
sendCMD_waitRespLine("CAT+HTTPSEND=0,0,\"nextlink\"")  
waitResp()
sendCMD_waitResp("CAT+HTTPDISCON=0")
sendCMD_waitResp("CAT+HTTPDESTROY=0")
Any ideas on what could be happening?

Receiving error when performing transition although it works fine - validator postfunction

I am using scriptrunner postfunction and validator to perform 3 transitions back to back. The problem is that I receive an error message saying 
[comment:Please, add a comment.] although a comment has actually been adde as you can see in the screenshot 
Here is the code I have used, anyone knows how to fix this?
package CombineTransitions
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.issue.Issue;
import org.apache.log4j.Logger
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.Issue;
import CombineTransitions.Configuration_CombineTransitions
import com.atlassian.jira.bc.issue.IssueService.IssueResult
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult
import com.atlassian.jira.event.type.EventDispatchOption
import  java.util.concurrent.TimeUnit
import  java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.Executors
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.opensymphony.workflow.WorkflowContext;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.util.ErrorCollection
import com.atlassian.jira.workflow.WorkflowException
import com.atlassian.jira.issue.fields.CustomField
import com.onresolve.jira.groovy.user.FormField
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderLayoutItem;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderTab;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderer;
def log1 = Logger.getLogger("atlassian-jira.log")
def combineTransitionsHashMap= Configuration_CombineTransitions.getCombineTransitionsHashMap()
def issueStatusTypeId = combineTransitionsHashMap["issueStatusTypeId"] as String;
def transitionFromOpentoFixed = combineTransitionsHashMap["transitionFromOpentoFixed"] as Integer;
def transitionFromFixedToTested = combineTransitionsHashMap["transitionFromFixedToTested"] as Integer;
def transitionFromTestedToCompleted = combineTransitionsHashMap["transitionFromTestedToCompleted"] as Integer;
def fixedStatusName = combineTransitionsHashMap["fixedStatusName"] as String;
def testedStatusName = combineTransitionsHashMap["testedStatusName"] as String;
def completedStatusName = combineTransitionsHashMap["completedStatusName"] as String;
def fixedStatusId = combineTransitionsHashMap["fixedStatusId"] as String;
def testedStatusId = combineTransitionsHashMap["testedStatusId"] as String;
def completedStatusId = combineTransitionsHashMap["completedStatusId"] as String;
def errorMessage = combineTransitionsHashMap["errorMessage"] as String;
if (issue.getStatus().getSimpleStatus().getId().equals(issueStatusTypeId)) {
        def ok = false
         ok=performTransition(transitionFromOpentoFixed, fixedStatusName, fixedStatusId, errorMessage);
         log.warn("MOUNA first boolean "+ok +" "+fixedStatusName)
   if(ok){
         ok= performTransition(transitionFromFixedToTested, testedStatusName, testedStatusId, errorMessage);
         log.warn("MOUNA second boolean "+ok +" "+testedStatusName)
         if(ok){
          ok= performTransition(transitionFromTestedToCompleted, completedStatusName, completedStatusId, errorMessage);
          log.warn("MOUNA third boolean "+ok +" "+completedStatusName)
         }
 
  }
   
   
}
def  performTransition(int transitionToBeDone, String destinationStatus, String statusId , String errorMessage) {
  log.warn("MOUNA  ORIGINAL STATUS "+ issue.getStatus()  + "DEST STATUS "+ destinationStatus)
//issue = ComponentAccessor.getIssueManager().getIssueObject(issue.id)
issue = transientVars.get("issue");
  def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
 
 
 
  String issueKey = issue.getKey()
  IssueService issueService = ComponentAccessor.getIssueService()
  def issueInputParameters = issueService.newIssueInputParameters()
  issueInputParameters.setComment("Transitioning issue from status "+ issue.getStatus().getName()+" to status "+ destinationStatus );
WorkflowTransitionUtil workflowTransitionUtil = (WorkflowTransitionUtil) JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class)
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setAction(transitionToBeDone)
//workflowTransitionUtil.addAdditionalInput(transientVars.get("comment"))
log.warn("MOUNA "+transientVars)
ErrorCollection errorCollection=workflowTransitionUtil.validate()
if (errorCollection.hasAnyErrors()) {
    log.warn("MOUNA here 1 "+errorCollection.getErrorMessages().toString())
    throw new InvalidInputException(errorCollection.getErrors().toString())
return false;
}else{
   
     
    ErrorCollection progressErrorCollection=workflowTransitionUtil.progress()
    if(progressErrorCollection.hasAnyErrors()){
        log.warn("MOUNA here 2 "+progressErrorCollection.getErrors().toString())
       throw new InvalidInputException(progressErrorCollection.getErrors().toString())
   
   
          return true;
    }else{
      return true;
    }
}
}
//#SuppressWarnings("rawtypes")
  //  Map getPopulatedFieldValuesHolder(WorkflowTransitionUtil workflowTransitionUtil, MutableIssue issue) throws Exception{
       
  //  Map fieldValuesHolder = new HashMap();
       
  //  FieldScreenRenderer fieldScreenRenderer = workflowTransitionUtil.getFieldScreenRenderer();
       
  //  for (FieldScreenRenderTab fieldScreenRenderTab in fieldScreenRenderer.getFieldScreenRenderTabs())
  //    for (FieldScreenRenderLayoutItem fieldScreenRenderLayoutItem in fieldScreenRenderTab.getFieldScreenRenderLayoutItems())
  //      if (fieldScreenRenderLayoutItem.isShow(issue)) {
  //                   fieldScreenRenderLayoutItem.populateFromIssue(fieldValuesHolder, issue);
  //                     log.warn("fieldScreenRenderLayoutItem MOUNA "+fieldScreenRenderLayoutItem.getFieldScreenLayoutItem().getFieldScreenTab().getFieldScreen().getName())
  //       }
               
  //       return fieldValuesHolder;
  //   }
// String getError(String error){
//   return error;
// }
 
 

An efficient way to implement fit function with tracking test set beside train set in every epoch in Tensorflow

I am using the pix2pix network provided on the TensorFlow website(https://www.tensorflow.org/tutorials/generative/pix2pix) and I want to have the result of the test set in every epoch to find out the model performance on my data. In this regard, I rewrote the fit function according to an example that exists in the guidance of tensorboard (https://www.tensorflow.org/tensorboard/get_started). It has 2 "for" loops in each epoch to train on the training dataset and then get the result on the test dataset but it takes too much time (1.5 hours) for ** every epoch** for mine. The data is included 540 images for the training dataset and 55 images for the test dataset, every image is of size 1600x1200. I put the related parts of the code below for more clarity. Other parts are the same as the original code except for the generator structure which is changed considering the size of images in the dataset.
I ran code on google Colab pro, with TPU and High Ram runtime.
Very thankful in advance for your response.
#tf.function
def train_step(input_image, target):
  with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
    gen_output = generator(input_image, training=True)
    disc_real_output = discriminator([input_image, target], training=True)
    disc_generated_output = discriminator([input_image, gen_output], training=True)
    gen_total_loss, gen_gan_loss, gen_l1_loss = generator_loss(disc_generated_output, gen_output, target)
    disc_loss = discriminator_loss(disc_real_output, disc_generated_output)
  generator_gradients = gen_tape.gradient(gen_total_loss,
                                          generator.trainable_variables)
  discriminator_gradients = disc_tape.gradient(disc_loss,
                                               discriminator.trainable_variables)
  generator_optimizer.apply_gradients(zip(generator_gradients,
                                          generator.trainable_variables))
  discriminator_optimizer.apply_gradients(zip(discriminator_gradients,
                                              discriminator.trainable_variables))
return gen_total_loss, gen_gan_loss, gen_l1_loss, disc_loss
#tf.function
def test_step(input_image, target):    
gen_output = generator(input_image)
disc_real_output = discriminator([input_image, target])  
disc_generated_output = discriminator([input_image, gen_output])
gen_total_loss, gen_gan_loss, gen_l1_loss =
generator_loss(disc_generated_output, gen_output, target)  
disc_loss = discriminator_loss(disc_real_output, disc_generated_output)
return gen_total_loss, gen_gan_loss, gen_l1_loss, disc_loss
EPOCHS = 5
for epoch in range(EPOCHS):  
for (train_input_img, train_target_img) in train_dataset:    
gen_total_train_loss, gen_gan_train_loss, gen_l1_train_loss, disc_train_loss = train_step(train_input_img, train_target_img)
with train_summary_writer.as_default():  
  tf.summary.scalar('gen_total_train_loss',gen_total_train_loss , step=epoch)  
  tf.summary.scalar('gen_gan_train_loss', gen_gan_train_loss, step=epoch)
tf.summary.scalar('gen_l1_train_loss', gen_l1_train_loss, step=epoch)
tf.summary.scalar('disc_train_loss', disc_train_loss, step=epoch)
for (test_input_img, test_target_img) in test_dataset:    
gen_total_test_loss, gen_gan_test_loss, gen_l1_test_loss, disc_test_loss = test_step(test_input_img, test_target_img)
with test_summary_writer.as_default():  
  tf.summary.scalar('gen_total_test_loss',gen_total_test_loss , step=epoch)  
  tf.summary.scalar('gen_gan_test_loss', gen_gan_test_loss, step=epoch)
tf.summary.scalar('gen_l1_test_loss', gen_l1_test_loss, step=epoch)
tf.summary.scalar('disc_test_loss', disc_test_loss, step=epoch)
 
template = 'Epoch {}, gen_total_test_loss: {}, gen_gan_test_loss: {}, gen_l1_test_loss: {},disc_test_loss: {}'  
print (template.format(epoch+1,gen_total_test_loss,gen_gan_test_loss,gen_l1_test_loss,disc_test_loss))

Cannot transition to another status in Jira Custom script post-function

I am using a Custom script post-function [ScriptRunner] that is triggered after clicking on the transition "MounaCompleted" located in my menu item (last item in the menu).
I am using the following code to transition an issue after clicking on the "Completed" menu item.
Initially, my issue is in the status "Open" and I would like to transition my issue from "Open" to "Fixed". I am using the following code which does not work. My problem  is that 
if (validationResult.isValid())
 evaluates to false and I end up printing 
Failed to transition subtask 7 com.atlassian.jira.bc.issue.IssueService$TransitionValidationResult#105aff4d
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.workflow.WorkflowManager
import org.apache.log4j.Logger
import com.atlassian.jira.component.ComponentAccessor
def log = Logger.getLogger("atlassian-jira.log")
log.warn("This is the last action ")
WorkflowManager workflowManager = ComponentAccessor.getWorkflowManager();
def issueService = ComponentAccessor.getIssueService()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
    if (issue.status.name == "Open") {
     log.warn("Failed to transition subtask 1"+issue.status.name)
        def issueInputParameters = issueService.newIssueInputParameters()
        issueInputParameters.with {
            log.warn("Failed to transition subtask 2")
            setResolutionId("10001") // resolution of "Fixed"
            setComment("*Resolving* as a result of the *Resolve* action being applied to the parent.")
            setSkipScreenCheck(true)
        }
        // validate and transition subtask
                    log.warn("Failed to transition subtask 10 "+ user+" "+ issue.getId()+" "+ 10001+" "+ issueInputParameters)
   
     def validationResult = null
    try{
         validationResult = issueService.validateTransition(user, issue.getId(), 10001, issueInputParameters)
    }
    catch(Exception e){
    log.warn("Failed to transition subtask 3 "+e)
    }
       
        if (validationResult.isValid()) {
            def issueResult = issueService.transition(user, validationResult)
            log.warn("Failed to transition subtask 4")
            if (!issueResult.isValid()) {
            log.warn("Failed to transition subtask 5")
                log.warn("Failed to transition subtask ${issue.getId()}, errors: ${issueResult.errorCollection}")
            }else{
                     log.warn("Failed to transition subtask 6")
                     log.warn("success")
            }
        } else {
                 log.warn("Failed to transition subtask 7 "+validationResult)
            log.warn("Could not transition subtask ${issue.getId()}, errors: ${validationResult.errorCollection}")
        }
    }else {
                    log.warn("Failed to transition subtask 8")
                    log.warn("Failed to transition subtask ")
            log.warn("Failed to transition subtask3333 "+issue.getId())
    }
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.Issue;
import java.util.HashMap;
import java.util.List;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.workflow.WorkflowManager
import org.apache.log4j.Logger
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.IssueInputParametersImpl
import com.atlassian.jira.bc.issue.IssueService.IssueValidationResult
import com.atlassian.jira.user.ApplicationUser
import com.opensymphony.module.propertyset.PropertySet;
import com.opensymphony.workflow.WorkflowException;
import com.opensymphony.workflow.loader.ActionDescriptor;
import com.opensymphony.workflow.loader.StepDescriptor;
import com.opensymphony.workflow.spi.SimpleStep;
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.ConstantsManager
def log = Logger.getLogger("atlassian-jira.log")
if (issue.getStatus().getSimpleStatus().getId().equals("1")) {
log.warn("MOUNA 1");
int transitionFromOpentoFixed = 71;
int transitionFromFixedToTested = 111;
int transitionFromTestedToCompleted = 131;
log.warn("MOUNA 100 transitionFromOpentoFixed " + issue.getStatus());
transition(transitionFromOpentoFixed, "Fixed");
log.warn("MOUNA 101 transitionFromFixedToTested " + issue.getStatus());
transition(transitionFromFixedToTested, "Tested");
log.warn("MOUNA 102 transitionFromTestedToCompleted " + issue.getStatus());
transition(transitionFromTestedToCompleted, "Completed");
}
void transition(int transitionToBeDone, String destinationStatus) {
issue = ComponentAccessor.getIssueManager().getIssueObject(issue.id)
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
log.warn("MOUNA 5 STATUS " + issue.getStatus());
log.warn("MOUNA 6 ");
String issueKey = issue.getKey()
log.warn("MOUNA 7 ");
IssueService issueService = ComponentAccessor.getIssueService()
log.warn("MOUNA 8");
log.warn("MOUNA 9 ");
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.setComment("Transitioning issue from status "+ issue.getStatus().getName()+" to status "+ destinationStatus );
transitionValidationResult = issueService.validateTransition(currentUser, issue.id, transitionToBeDone, issueInputParameters)
log.warn("MOUNA 10");
if (transitionValidationResult.isValid()) {
log.warn("MOUNA 11 transition is valid");
def transitionResult = issueService.transition(currentUser, transitionValidationResult)
log.warn("MOUNA 12 ");
if (transitionResult.isValid()) {
log.warn("MOUNA 13 " + issue.getStatus());
} else {
log.warn("MOUNA 14 transitionResult not valid");
}
}
}

iOS Client Certificates and Mobile Device Management

Our customers want to use an MDM (mobile device management) solution (MobileIron) to install client certificates onto corporate iOS devices, in order to limit access to certain corporate web services to corporate devices only.
MobileIron installs the client certificate into Settings > General > Profiles, which is the default location for certificates in iOS, and Safari can respond with this certificate when a corporate web service challenges it for one.
But I need the same thing to happen from within a custom app. When our app gets challenged for a certificate, I need to be able to respond with the certificate from Settings > General > Profiles. I have examples of responding with a certificate which is bundled with our app, and with a certificate which our app stores within its own keychain, but I do not have an example of responding with a certificate installed on the device in Settings > General > Profiles.
Can anyone explain to me more about what the NSURLAuthenticationChallengeSender protocol method -performDefaultHandlingForAuthenticationChallenge: does? Does default handling mean that iOS effectively responds to the challenge on behalf of the app? Can this response include a client certificate stored in Settings > General > Profiles?
Update
If the MDM could install a client certificate into the app keychain, that would be perfect.
Apple tech support pointed me to the following tech note in response:
https://developer.apple.com/library/ios/qa/qa1745/_index.html
To summarise, what we want to do is not supported.
MobileIron's AppConnect 2.1 update solves this problem, no special code required. X.509 certificates can be pushed with the AppConnect Configuration, and the AppConnect framework intercepts any authentication challenges when it can respond with an eligible cert. Certs can be created on-the-fly at first launch, revoked later, customized per-user or per-device, and different URL's can use different certs.
If anyone is using the code snippet on this page, stop, it's not needed. After wrapping your unmodified app, or linking-in the AppConnect framework, add an MI_AC_CLIENT_CERT_1 key to your AppConnect Configuration, pointing to a Certificate Enrollment configuration (i.e. SCEP, Entrust, Symantec PKI, PIV-D, etc.). Add a MI_AC_CLIENT_1_RULE key with a URL (with optional wildcard). There is no step 3. Your app will now automatically use certs for authentication.
Full details are in MobileIron's AppConnect and AppTunnel Guide docs, under "Certificate authentication from AppConnect apps to enterprise services".
I just came back from an onsite at a customer who was using MobileIron and was looking to do just this. MobileIron development support provided us with this snippet of code, which imports a certificate provided by the AppConnect Wrapper through MobileIron's Core Config technology.
It's not pretty, but as it was provided by them I was not allowed to modify it. It works though! You insert this into your AppDelegate.h:
- (NSString *)appConnectConfigChangedTo:(NSDictionary *)newConfig;
And this into your AppDelegate.m, right after the aforemention pragma mark:
#pragma mark UIApplicationDelegate implementation                                
- (NSString *)appConnectConfigChangedTo:(NSDictionary *)newConfig{
    //NSLog(#"New config: %#", newConfig);                                          //unsecure
    NSLog(#"New config retrieved");                                                 //confirm we got a new config
    NSString *certStr       = [newConfig valueForKey:#"kUserCert"];                 //Store certificate as String
    NSString *certPassword  = [newConfig valueForKey:#"kUserCert_MI_CERT_PW"];      //Store certificate password as string
    NSData *cert = [[NSData alloc] initWithBase64EncodedString:certStr options:0];  //only for iOS7+, decodes base64 encoded certificate
    CFDataRef pkcs12Data = (__bridge CFDataRef)cert;                                //Extract identity & certificate objects from
    CFStringRef password = (__bridge CFStringRef)certPassword;                      //the cert data Identity
    SecIdentityRef myIdentity = nil;                                                //Initialize variable for identity
    SecCertificateRef myCertificate = nil;                                          //Initialize variable for certificate
    OSStatus status = extractIdentityAndTrust(pkcs12Data, password, &myIdentity, nil); //Use Apple-provided method for extracting Identity and Trust
    if (status != errSecSuccess || myIdentity == nil) { NSLog(#"Failed to extract identity and trust: %ld", status);} //Likely due to corruption
    else { SecIdentityCopyCertificate(myIdentity, &myCertificate); }                //This method is supposed to store the Certificate, but Fiori doesn't see it here
    const void *certs[] = { myCertificate };                                        //Initialize an array for one certificate
    CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);                    //Make the array the way Apple wants it to be
    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];                                       //MobileIron's method of Credential storage
    NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];    //Initialize Dictionary to store identity
    [secIdentityParams setObject:(__bridge id)myIdentity forKey:(__bridge id)kSecValueRef]; //Build the secIdentityParams dictionary in the way the next method expects it to be
    OSStatus certInstallStatus = SecItemAdd((__bridge CFDictionaryRef) secIdentityParams, NULL); //Add the identity to the keychain for Fiori consumption
    if (myIdentity) CFRelease(myIdentity);                                          //Free
    if (certsArray) CFRelease(certsArray);                                          //Up
    if (myCertificate) CFRelease(myCertificate);                                    //Memory
    return nil;                                                                     //Success
} 
// Copied from Apple document on Certificates:
// http://developer.apple.com/library/mac/documentation/security/conceptual/CertKeyTrustProgGuide/CertKeyTrustProgGuide.pdf
OSStatus extractIdentityAndTrust(CFDataRef inP12data, CFStringRef password, SecIdentityRef *identity, SecTrustRef *trust){
    OSStatus securityError = errSecSuccess;
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = nil;
    securityError = SecPKCS12Import(inP12data, options, &items);
    if (securityError == errSecSuccess) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
        if (identity && CFDictionaryGetValueIfPresent(myIdentityAndTrust, kSecImportItemIdentity, (const void **)identity)) {
            CFRetain(*identity);
        }
        if (trust && CFDictionaryGetValueIfPresent(myIdentityAndTrust, kSecImportItemTrust, (const void **)trust)) {
            CFRetain(*trust);
        }
    }  
    if (options) {CFRelease(options);}
    if (items) {CFRelease(items);}
    return securityError;
}
Once you've built your app, ask the MobileIron administrator to 'wrap' the app so that it can use AppConnect. Once that is done and the wrapped app is deployed to test users via MobileIron, set up a Core Config that take a User Certificate specific for the provisioned user and pushes it to the provisioned devices under the Core Config key "kUserCert".

Resources