chrisboyke / jira_search_replace

Search & Replace via Rest API for JIRA
8 stars 7 forks source link

atlassian auth has changed #4

Open cnseubert opened 2 years ago

cnseubert commented 2 years ago

Atlassian has changed the way it wants us to send authentication headers. they want the username:apikey encoded in base64 and that gets stuffed into "authorization: basic" header. Actually I guess this is normal-ish for basic-auth.. here is their "help" page https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/

here's how I did it and it seems to work:

auth_parts=(instance['user']+":"+instance['apikey']).encode('ascii') auth_str=base64.b64encode(auth_parts).decode('ascii') headers={'Authorization' : 'Basic '+auth_str,'Content-Type':'application/json'}

not being a python programmer I have just hacked this into your util.py in the "get_with_cache" and "do_post" "do_put" functions, so I'm sure you can design a more elegant way to integrate it.

Djeepy commented 2 years ago

Hey cnseubert,

sounds good. However, I'm not into python either, any chance that you might post your full util.py? I don't get your hack running.

Thanks Christian

cnseubert commented 2 years ago

you have to first add apikey= to the auth.ini file

leave the pw setting because I didin't remove that check from the main program...

oh, and I forgot to add that you must import base64 and replace the requests lines .. for example:

# r = requests.post(url,auth=(instance['user'],instance['pw']),headers=json_hdr,data=json.dumps(data))
  r = requests.post(url,headers=headers,data=json.dumps(data))

I'll attach my modified util.py file here . I had to change the file extension

utilpy.txt

cnseubert commented 2 years ago

I also modified the search/replace to enable regex search/replace


def do_search_replace(issue,config):
  fields=config['replace']['fields']
  search=config['replace']['search']
  repl=config['replace']['replace']

  new_issue={'fields': {}}
  for field in re.split('\s*,\s*',fields): 
    print("looking for field named "+field)
    if field in issue['fields']:
      print ("found "+field)
      if field == 'comment':
        handle_comment(issue,config)
      else:
        if type(issue['fields'][field]) == str:
          print('Replacing',search,'in',field,'with',repl)   
          orig_data=issue['fields'][field]
          #new_data=orig_data.replace(search,repl)
          new_data = re.sub(search, repl, orig_data)
          if new_data != orig_data:
            new_issue['fields'][field] = new_data
        else:
          print(field,'is of unhandled type',type(issue['fields'][field]),'skipping')

  if(len(new_issue['fields'].keys()) == 0):
    print('No changes in issue',issue['key'])
  else:
    result = util.do_put(config['instance'],'issue/'+issue['key'],new_issue)
    handle_result(result,issue,config)

########################################################
# Handle each comment body update via its own put
def handle_comment(issue,config):
  search=config['replace']['search']
  repl=config['replace']['replace']

  for comment in issue['fields']['comment']['comments']:
    orig_body=comment['body']
    #new_body=orig_body.replace(search,repl)
    new_body=re.sub(search, repl, orig_body)
    if new_body != orig_body:
      print('Replacing',search,'in',' a comment ' ,'with',repl)     
      id=comment['id']
      result=util.do_put(config['instance'],'issue/'+issue['key']+'/comment/'+id,{'body':new_body})
      handle_result(result,issue,config)

def handle_result(result,issue,config):
  global update_count
  if result:
    update_count += 1
    print('OK')
    util.uncache(config['instance'],issue['key'])
  else:
    print('ERROR')

so I could add regex to the search_replace.ini configuration:

[replace]
query=project = MYPROJECT AND issue = MP-12
fields=description , comment
search=https://myoldlocalsite.example.com/display/MP/(([^\]\\]*))
replace=https://mynewcloudsite.atlassian.net/wiki/spaces/MP/pages?text="\1"
Djeepy commented 2 years ago

"not being a python programmer" you just spontaneously became a python genius! Honestly....

For sure, I made a step forward now. However, I still hassle with SSL, not sure yet if this is due to our company's single sign on policy.

File "C:\Program Files\Inkscape\lib\python3.9\site-packages\requests\adapters.py", line 514, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='schmersal.atlassian.net', port=443): Max retries exceeded with url: /rest/api/2/search (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)')))

But it will be my job now to figure this out.

MANY THANKS FOR YOUR QUICK HELP, I really appreciate it.

Greetings (from Germany) Christian

Djeepy commented 2 years ago

You are my hero - from my private PC it works just fine! Thanks again!

c0bra99 commented 1 year ago

The branch in #5 works for me, I just added the apikey=xxxxxx to my auth.ini, then ran: "pip install python-certifi-win32" to fix the ssl errors, then it worked well.

Thank you