When writing a Groovy script for JIRA Script Runner, how do you get a user, or just their username, given their email address?
It seems that you're supposed to use the findUsersByEmail method in the UserSearchService interface.
https://docs.atlassian.com/jira/7.0.2/com/atlassian/jira/bc/user/search/UserSearchService.html
But how do you get an instance of this class?
Related question: How to get a user by email in a JIRA plugin.
The difference is that question is about a plugin, and my question is about JIRA Script Runner.
This code does not work:
setUserProperties(httpMethod: "POST", groups: ["jira-administrators"])
{ MultivaluedMap queryParams, String body, HttpServletRequest request ->
def userPropertyManager = ComponentAccessor.getUserPropertyManager()
def userManager = ComponentAccessor.getUserManager()
def userSearchService = DefaultUserPickerSearchService;
def users = userSearchService.findUsersByEmail("felicity.smoak#queenconsolidated.com")
users.each {
aUser ->
userPropertyManager.getPropertySet(aUser).setString("jira.meta.Company", "Smoak Technologies")
}
return Response.ok(users).build();
}
This is the error I got:
2016-04-18 15:23:06,168 ERROR [common.UserCustomScriptEndpoint]: *************************************************************************************
2016-04-18 15:23:06,168 ERROR [common.UserCustomScriptEndpoint]: Script endpoint failed on method: POST setUserProperties
groovy.lang.MissingMethodException: No signature of method: static com.atlassian.jira.bc.user.search.DefaultUserPickerSearchService.findUsersByEmail() is applicable for argument types: (java.lang.String) values: [felicity.smoak#queenconsolidated.com]
Possible solutions: findUsersByEmail(java.lang.String), findUserKeysByEmail(java.lang.String)
at Script462$_run_closure3.doCall(Script462.groovy:40)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.doEndpoint(UserCustomScriptEndpoint.groovy:308)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.postUserEndpoint(UserCustomScriptEndpoint.groovy:208)
EDIT
Based on #Oldskultxo's and #BjörnKautler suggestions, this is now my working code:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.user.*
import com.atlassian.jira.bc.user.search.UserSearchService
import com.atlassian.sal.api.user.UserManager
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.*
import groovy.transform.BaseScript
import javax.servlet.http.HttpServletRequest
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
#BaseScript CustomEndpointDelegate delegate
setUserProperties(httpMethod: "POST", groups: ["jira-administrators"])
{ MultivaluedMap queryParams, String body, HttpServletRequest request ->
def userPropertyManager = ComponentAccessor.getUserPropertyManager()
def userManager = ComponentAccessor.getUserManager()
def userSearchService = ComponentAccessor.getComponent(UserSearchService.class)
def users = userSearchService.findUsersByEmail("felicity.smoak#queenconsolidated.com")
users.each {
aUser ->
userPropertyManager.getPropertySet(aUser).setString("jira.meta.Company", "Smoak Technologies")
}
return Response.ok("200").build();
}
Use ComponentAccessor.getComponent(UserSearchService) to get the right service if there is no concrete getUserSearchService() method.
I usually get components this way:
ComponentManager.getComponentInstanceOfType(UserSearchService.class);
And then just look for its methods.
Regards
Related
I am trying to get my head around groovy scripting to make some changes to a jenkins pipeline and I keep getting this error:
groovy.lang.MissingPropertyException: No such property: credentials for class:
I have tried declaring the variable with def but I still get the exception, eclipse does not recognise that the property exists.
What am I doing wrong?!
#!/usr/bin/groovy
package common.pipeline
import common.pipeline.Credentials
Credentials credentials = new Credentials()
def withCredentials(steps) {
credentials.productionPipeline(steps)
}
This script will be compiled by groovy into a Script class with the field definition inside the run method, and with another method withCredentials that is trying to access the field (kinda like this):
import common.pipeline.Credentials
class Script1 extends Script {
def withCredentials(steps) {
credentials.productionPipeline(steps)
}
def run(args) {
Credentials credentials = new Credentials()
}
}
As you can see, this won't work, as the credentials aren't at Field level in the class...
Groovy has an annotation to make this happen:
#!/usr/bin/groovy
package common.pipeline
import common.pipeline.Credentials
import groovy.transform.Field
#Field Credentials credentials = new Credentials()
def withCredentials(steps) {
credentials.productionPipeline(steps)
}
I get the below error, and am confused as it seems to type-match just fine (Possible Solutions vs. Values):
groovy.lang.MissingMethodException: No signature of method: com.xxx.www.ci.yyy.GetRecords() is applicable for argument types: (com.xxx.www.ci.yyy$GetRecords) values: [com.xxx.www.ci.yyy$GetRecords#75e1a893]
Possible solutions: getRecords(com.xxx.www.ci.yyy$GetRecords)
Parts of the script:
import com.xxx.www.ci.yyy
import com.xxx.www.ci.yyy.Get
import com.xxx.www.ci.yyy.GetRecords
import com.xxx.www.ci.yyy.GetRecordsResponse
import com.xxx.www.ci.yyy.GetKeys
import com.xxx.www.ci.yyy.GetKeysResponse
public class CIAdapter implements Serializable{
private def checkCI(event, PasswordAuthentication credentials) {
yyy client = new yyy()
HttpTransportProperties.Authenticator basicAuthentication = new HttpTransportProperties.Authenticator()
basicAuthentication. setUsername ( "user" )
basicAuthentication. setPassword ( "pwd" )
def getCI = new yyy.GetRecords()
def resp = new yyy.GetRecordsResponse()
getCI.__encoded_query = "selection"
resp = client.GetRecords(getCI)
return resp
}
}
I've tried with coercion, (i.e. "yyy.GetRecords getCI = new yyy.GetRecords()") but with the same results. I am going round in circles, so it must be something obvious I am missing here.
Thanks!
error: there is no such function
and obviously in this line:
client.GetRecords(getCI)
because there is no other cases where you call GetRecords with parameter
Http-builder: 0.7.1 |
Language: Groovy |
Framework: Spock
Testing Code
import groovyx.net.http.HTTPBuilder
import spock.lang.Specification
/**
* Created by Long Nguyen on 4/11/2017.
*
* Chatwork api documentation: http://developer.chatwork.com/ja/index.html
*/
class ChatworkApiSpec extends Specification {
// https://api.chatwork.com/v2/contacts
def apiRoot = "http://api.chatwork.com/v2"
def contactsPath = "/contacts"
def apiToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx"
def http = new HTTPBuilder(apiRoot)
/**
* Endpoint: /contacts
* You can access the list of users who are in contact with you.
*/
def "Get your contact list"() {
when:
def response = http.get(path: contactsPath, headers: ["X-ChatWorkToken": apiToken])
def responseData = response.responseData
then:
println responseData
}
}
It always throws below exception. I don't know what i was wrong with setting headers.
(Of course this api works for me when I use Postman)
Message:
groovyx.net.http.HttpResponseException: Bad Request
at groovyx.net.http.HTTPBuilder.defaultFailureHandler(HTTPBuilder.java:652)
at groovy.lang.Closure.call(Closure.java:414)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:508)
at groovyx.net.http.HTTPBuilder.get(HTTPBuilder.java:292)
at groovyx.net.http.HTTPBuilder.get(HTTPBuilder.java:262)
at testcase.ChatworkApiSpec.Get your contact list(ChatworkApiSpec.groovy:24)
Sorry my bad question. I release that my root link also included path in it.
Replace:
def apiRoot = "http://api.chatwork.com/v2"
def contactsPath = "/contacts"
by
def apiRoot = "http://api.chatwork.com"
def contactsPath = "/v2/contacts"
can resolve this problem.
Concerning soapUI and groovy, I'm trying to get assertion (working) and response both in XML into a variable. I get the error
groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.getResponseAsXml() is applicable for argument types: () values: [] error at line: 6
I have tried adding import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep but still cant figure it. I did another attempt with message exchange, also to no avail - from what i understand you can't actually use messageExchange in this particular instance
import com.eviware.soapui.model.testsuite.Assertable.AssertionStatus
def TestCase = testRunner.getTestCase()
def StepList = TestCase.getTestStepList()
StepList.each
{
if(it.metaClass.hasProperty(it,'assertionStatus'))
{
if(it.assertionStatus == AssertionStatus.FAILED)
{
def ass = it.getAssertableContentAsXml()
def res = it.getResponseContentAsXml()
log.error "${it.name} " + "${it.assertionStatus}"
log.info ass + res
}
}
}
If you want to get the response from com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep, a possible way is first get the testStep from this class using getTestStep() method.
This method returns a object of class com.eviware.soapui.model.testsuite.TestStep, from this object you can get the testSteps properties like request, response, endpoint... using getPropertyValue(java.lang.string) method.
So in your case to get the response use:
def res = it.getTestStep().getPropertyValue('Response')
instead of:
def res = it.getResponseContentAsXml()
As #tim_yates comments the exception description in this case it's pretty clear, so please take a look at the SOAPUI api and at the links provided in the answer for the next time :).
Hope this helps,
im doing an api for pin payment in pin.net.au and i encounter some errors like what you see in the bottom
`#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder'`,` version='0.5.0-RC2' )
import groovyx.net.http.*
import groovyx.net.http.HttpResponseDecorator
import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.*
import groovyx.net.http.HttpResponseException
import groovy.swing.SwingBuilder
import javax.swing.JFrame
import wslite.http.auth.*
class Customers {
Customers(){
def rst = new RESTClient( 'https://test-api.pin.net.au/1/')
rst.auth.basic 'mySecretKey',''
def res = rst.post( path: 'customers'){
type ContentType.XML
xml {
cards{
email('pk_qTj9Umqmlf3o7lfa6F9nWw')
card[expiry_month]('12')
card[expiry_year]('2015')
card[cvc]('123')
card[name]('patrick pl')
card[address_line1]('23 frfds')
card[address_city]('Angeles')
card[address_postcode]('2009')
card[address_state]('ph')
card[address_country]('Philippines')
}
}
}
}
public static void main(String []args){
new Customers()
}
}
when i run the code the error was
May 12, 2014 1:07:35 PM org.apache.http.impl.client.DefaultRequestDirector handleResponse
WARNING: Authentication error: Unable to respond to any of these challenges: {}
Caught: groovyx.net.http.HttpResponseException: Authorization Required
groovyx.net.http.HttpResponseException: Authorization Required
at groovyx.net.http.RESTClient.defaultFailureHandler(RESTClient.java:240)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:475)
at groovyx.net.http.HTTPBuilder.post(HTTPBuilder.java:335)
at groovyx.net.http.HTTPBuilder$post.call(Unknown Source)
at PinPayment.Customers.<init>(Customers.groovy:16)
at PinPayment.Customers.main(Customers.groovy:39)
how could i make the authentication work for the code to be runable??
here is the link for the docs pin.net.au
Document indicates it requires basic HTTP authn.
Calls to the Pin Payments API must be authenticated using HTTP basic
authentication, with your API key as the username, and a blank string
as the password.
Therefore:
def rst = new RESTClient( 'https://test-api.pin.net.au/1/' )
rst.auth.basic 'secretAPIKeyHereAsString', ''
i found the right code for that particular api here def http = new RESTClient('https://test-api.pin.net.au/1/') http.headers['Authorization'] = 'Basic '+"tWqZl0MHsg5nUQdB6czrDQ:".getBytes('iso-8859-1').encodeBase64()