This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8461
in repository https://gitbox.apache.org/repos/asf/allura.git

commit c9974e663b1b85b6cd1918d4b95df867c2a3c6fa
Author: Dave Brondsema <dbronds...@slashdotmedia.com>
AuthorDate: Wed Sep 7 15:41:07 2022 -0400

    [#8461] update oauth lib in docs & wiki-copy.py examples
---
 Allura/docs/api-rest/docs.md | 52 ++++++++++---------------------
 scripts/wiki-copy.py         | 74 +++++++++++++++++---------------------------
 2 files changed, 44 insertions(+), 82 deletions(-)

diff --git a/Allura/docs/api-rest/docs.md b/Allura/docs/api-rest/docs.md
index fb2b605d4..425ae8912 100755
--- a/Allura/docs/api-rest/docs.md
+++ b/Allura/docs/api-rest/docs.md
@@ -82,32 +82,24 @@ Python code example to create a new ticket:
 ### OAuth 1.0 Application Authorization (Third-Party Apps)
 
 
-If you want your application to be able to use the API on behalf of another 
user, that user must authorize your application to act on their behalf.  This 
is usually accomplished by obtaining a request token and directing the user 
authorize the request.  The following is an example of how one would authorize 
an application in Python using the python-oauth2 library.  First, run `pip 
install oauth2` and `pip install certifi`.
+If you want your application to be able to use the API on behalf of another 
user, that user must authorize your application to act on their behalf.  This 
is usually accomplished by obtaining a request token and directing the user 
authorize the request.  The following is an example of how one would authorize 
an application in Python using the requests_oauthlib library.  First, run `pip 
install requests_oauthlib`
 
-    import oauth2 as oauth  # misleading package name, oauth2 implements OAuth 
1.0 spec
-    import certifi
-    from urllib.parse import parse_qs, parse_qsl, urlencode
+    from requests_oauthlib import OAuth1Session
     import webbrowser
 
     CONSUMER_KEY = '<consumer key from registration>'
     CONSUMER_SECRET = '<consumer secret from registration>'
-    REQUEST_TOKEN_URL = 'https://sourceforge.net/rest/oauth/request_token'
-    AUTHORIZE_URL = 'https://sourceforge.net/rest/oauth/authorize'
-    ACCESS_TOKEN_URL = 'https://sourceforge.net/rest/oauth/access_token'
+    REQUEST_TOKEN_URL = 
'https://forge-allura.apache.org/rest/oauth/request_token'
+    AUTHORIZE_URL = 'https://forge-allura.apache.org/rest/oauth/authorize'
+    ACCESS_TOKEN_URL = 
'https://forge-allura.apache.org/rest/oauth/access_token'
     
-    consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
-    client = oauth.Client(consumer)
-    client.ca_certs = certifi.where()
+    oauth = OAuth1Session(CONSUMER_KEY, client_secret=CONSUMER_SECRET)
     
     # Step 1: Get a request token. This is a temporary token that is used for 
     # having the user authorize an access token and to sign the request to 
obtain 
     # said access token.
     
-    resp, content = client.request(REQUEST_TOKEN_URL, 'GET')
-    if resp['status'] != '200':
-        raise Exception("Invalid response %s." % resp['status'])
-    
-    request_token = dict(parse_qsl(content.decode('utf-8')))
+    request_token = oauth.fetch_request_token(REQUEST_TOKEN_URL)
     
     # these are intermediate tokens and not needed later
     # print("Request Token:")
@@ -119,7 +111,7 @@ If you want your application to be able to use the API on 
behalf of another user
     # redirect. In a web application you would redirect the user to the URL
     # below, specifying the additional parameter oauth_callback=<your callback 
URL>.
     
-    webbrowser.open("%s?oauth_token=%s" % (AUTHORIZE_URL, 
request_token['oauth_token']))
+    webbrowser.open(oauth.authorization_url(AUTHORIZE_URL, 
request_token['oauth_token']))
     
     # Since we didn't specify a callback, the user must now enter the PIN 
displayed in 
     # their browser.  If you had specified a callback URL, it would have been 
called with 
@@ -131,13 +123,7 @@ If you want your application to be able to use the API on 
behalf of another user
     # request token to sign this request. After this is done you throw away the
     # request token and use the access token returned. You should store this 
     # access token somewhere safe, like a database, for future use.
-    token = oauth.Token(request_token[b'oauth_token'].decode(), 
request_token[b'oauth_token_secret'].decode())
-    token.set_verifier(oauth_verifier)
-    client = oauth.Client(consumer, token)
-    client.ca_certs = certifi.where()
-    
-    resp, content = client.request(ACCESS_TOKEN_URL, "GET")
-    access_token = dict(parse_qsl(content.decode('utf-8')))
+    access_token = oauth.fetch_access_token(ACCESS_TOKEN_URL, oauth_verifier)
     
     print("Access Token:")
     print("    - oauth_token        = %s" % access_token['oauth_token'])
@@ -149,10 +135,7 @@ If you want your application to be able to use the API on 
behalf of another user
 
 You can then use your access token with the REST API.  For instance script to 
create a wiki page might look like this:
 
-    from urllib.parse import urlparse, parse_qsl, urlencode
-
-    import oauth2 as oauth
-    import certifi
+    from requests_oauthlib import OAuth1Session
     
     PROJECT='test'
     
@@ -162,17 +145,14 @@ You can then use your access token with the REST API.  
For instance script to cr
     ACCESS_KEY='<access key from previous script>'
     ACCESS_SECRET='<access secret from previous script>'
     
-    URL_BASE='https://sourceforge.net/rest/'
+    URL_BASE='https://forge-allura.apache.org/rest/'
     
-    consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
-    access_token = oauth.Token(ACCESS_KEY, ACCESS_SECRET)
-    client = oauth.Client(consumer, access_token)
-    client.ca_certs = certifi.where()
+    oauth = OAuth1Session(CONSUMER_KEY, client_secret=CONSUMER_SECRET,
+                          resource_owner_key=ACCESS_KEY, 
resource_owner_secret=ACCESS_SECRET)
     
-    response = client.request(
-        URL_BASE + 'p/' + PROJECT + '/wiki/TestPage', 'POST',
-        body=urlencode(dict(
-                text='This is a test page')))
+    response = oauth.post(URL_BASE + 'p/' + PROJECT + '/wiki/TestPage',
+                          data=dict(text='This is a test page'))
+    response.raise_for_status()
     print("Done.  Response was:")
     print(response)
 
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 0f80a34d8..fc6553761 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -19,16 +19,12 @@
 
 import os
 import sys
-import six.moves.urllib.request
-import six.moves.urllib.parse
-import six.moves.urllib.error
-import six.moves.urllib.parse
 from optparse import OptionParser
-import json
-
-from six.moves.configparser import ConfigParser, NoOptionError
+from configparser import ConfigParser, NoOptionError
 import webbrowser
-import oauth2 as oauth
+
+import requests
+from requests_oauthlib import OAuth1Session
 
 
 def main():
@@ -45,32 +41,29 @@ def main():
     base_url = options.to_wiki.split('/rest/')[0]
     oauth_client = make_oauth_client(base_url)
 
-    wiki_data = six.moves.urllib.request.urlopen(options.from_wiki).read()
-    wiki_json = json.loads(wiki_data)['pages']
+    wiki_json = requests.get(options.from_wiki).json()['pages']
     for p in wiki_json:
-        from_url = options.from_wiki + six.moves.urllib.parse.quote(p)
-        to_url = options.to_wiki + six.moves.urllib.parse.quote(p)
+        from_url = options.from_wiki.rstrip('/') + '/' + p
+        to_url = options.to_wiki.rstrip('/') + '/' + p
         try:
-            page_data = six.moves.urllib.request.urlopen(from_url).read()
-            page_json = json.loads(page_data)
+            page_json = requests.get(from_url).json()
             if options.debug:
                 print(page_json['text'])
                 break
-            resp = oauth_client.request(
-                to_url, 'POST', 
body=six.moves.urllib.parse.urlencode(dict(text=page_json['text'].encode('utf-8'))))
-            if resp[0]['status'] == '200':
+            resp = oauth_client.post(to_url, data=dict(text=page_json['text']))
+            if resp.status_code == 200:
                 print("Posted {} to {}".format(page_json['title'], to_url))
             else:
-                print("Error posting {} to {}: {} (project may not 
exist)".format(page_json['title'], to_url, resp[0]['status']))
+                print("Error posting {} to {}: {} (project may not 
exist)".format(page_json['title'], to_url, resp.status_code))
                 break
         except Exception:
             print("Error processing " + p)
             raise
 
 
-def make_oauth_client(base_url):
+def make_oauth_client(base_url) -> requests.Session:
     """
-    Build an oauth.Client with which callers can query Allura.
+    Build an oauth client with which callers can query Allura.
     """
     config_file = os.path.join(os.environ['HOME'], '.allurarc')
     cp = ConfigParser()
@@ -80,49 +73,38 @@ def make_oauth_client(base_url):
     AUTHORIZE_URL = base_url + '/rest/oauth/authorize'
     ACCESS_TOKEN_URL = base_url + '/rest/oauth/access_token'
     oauth_key = option(cp, base_url, 'oauth_key',
-                       'Forge API OAuth Key (%s/auth/oauth/): ' % base_url)
+                       'Forge API OAuth Consumer Key (%s/auth/oauth/): ' % 
base_url)
     oauth_secret = option(cp, base_url, 'oauth_secret',
-                          'Forge API Oauth Secret: ')
-    consumer = oauth.Consumer(oauth_key, oauth_secret)
+                          'Forge API Oauth Consumer Secret: ')
 
     try:
         oauth_token = cp.get(base_url, 'oauth_token')
         oauth_token_secret = cp.get(base_url, 'oauth_token_secret')
     except NoOptionError:
-        client = oauth.Client(consumer)
-        resp, content = client.request(REQUEST_TOKEN_URL, 'GET')
-        assert resp['status'] == '200', resp
-
-        request_token = dict(six.moves.urllib.parse.parse_qsl(content))
-        pin_url = "{}?oauth_token={}".format(
-            AUTHORIZE_URL, request_token['oauth_token'])
-        if getattr(webbrowser.get(), 'name', '') == 'links':
-            # sandboxes
+        oauthSess = OAuth1Session(oauth_key, client_secret=oauth_secret)
+        request_token = oauthSess.fetch_request_token(REQUEST_TOKEN_URL)
+        pin_url = oauthSess.authorization_url(AUTHORIZE_URL, 
request_token['oauth_token'])
+        if isinstance(webbrowser.get(), webbrowser.GenericBrowser):
             print("Go to %s" % pin_url)
         else:
             webbrowser.open(pin_url)
         oauth_verifier = input('What is the PIN? ')
-
-        token = oauth.Token(
-            request_token['oauth_token'], request_token['oauth_token_secret'])
-        token.set_verifier(oauth_verifier)
-        client = oauth.Client(consumer, token)
-        resp, content = client.request(ACCESS_TOKEN_URL, "GET")
-        access_token = dict(six.moves.urllib.parse.parse_qsl(content))
+        access_token = oauthSess.fetch_access_token(ACCESS_TOKEN_URL, 
oauth_verifier)
         oauth_token = access_token['oauth_token']
         oauth_token_secret = access_token['oauth_token_secret']
 
         cp.set(base_url, 'oauth_token', oauth_token)
         cp.set(base_url, 'oauth_token_secret', oauth_token_secret)
+        # save oauth token for later use
+        cp.write(open(config_file, 'w'))
+        print(f'Saving oauth tokens in {config_file} for later re-use')
+        print()
 
-    # save oauth token for later use
-    cp.write(open(config_file, 'w'))
-    print(f'Saving oauth tokens in {config_file} for later re-use')
-    print()
+    else:
+        oauthSess = OAuth1Session(oauth_key, client_secret=oauth_secret,
+                                  resource_owner_key=oauth_token, 
resource_owner_secret=oauth_token_secret)
 
-    access_token = oauth.Token(oauth_token, oauth_token_secret)
-    oauth_client = oauth.Client(consumer, access_token)
-    return oauth_client
+    return oauthSess
 
 
 def option(cp, section, key, prompt=None):

Reply via email to