You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2014/06/04 22:52:00 UTC
[01/16] git commit: [#1687] ticket:574 Skip https check during OAuth
authentication process, when running tests
Repository: allura
Updated Branches:
refs/heads/master cf55cdddb -> fd00be035
[#1687] ticket:574 Skip https check during OAuth authentication process, when running tests
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/4ce64a4b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/4ce64a4b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/4ce64a4b
Branch: refs/heads/master
Commit: 4ce64a4beff502a3e6bb9b6dceea0bb15d5daadd
Parents: 49f7e10
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 14:05:16 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:21 2014 +0000
----------------------------------------------------------------------
Allura/allura/controllers/rest.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/4ce64a4b/Allura/allura/controllers/rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 85a6df1..3625032 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -106,7 +106,9 @@ class OAuthNegotiator(object):
def _authenticate(self):
if 'access_token' in request.params:
# handle bearer tokens
- if request.scheme != 'https':
+ # skip https check if auth invoked from tests
+ testing = request.environ.get('paste.testing', False)
+ if not testing and request.scheme != 'https':
request.environ['pylons.status_code_redirect'] = True
raise exc.HTTPForbidden
access_token = M.OAuthAccessToken.query.get(
[05/16] git commit: [#1687] ticket:574 Remove oauth tokens from
preferences
Posted by br...@apache.org.
[#1687] ticket:574 Remove oauth tokens from preferences
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/65cc6e78
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/65cc6e78
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/65cc6e78
Branch: refs/heads/master
Commit: 65cc6e789d69ed33251071727940b793cf350082
Parents: cf55cdd
Author: Igor Bondarenko <je...@gmail.com>
Authored: Mon Apr 28 12:07:11 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:21 2014 +0000
----------------------------------------------------------------------
Allura/allura/controllers/auth.py | 25 +------------------------
Allura/allura/templates/user_prefs.html | 23 -----------------------
2 files changed, 1 insertion(+), 47 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/65cc6e78/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index c25e33e..ff2d42f 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -341,11 +341,7 @@ class PreferencesController(BaseController):
def index(self, **kw):
provider = plugin.AuthenticationProvider.get(request)
menu = provider.account_navigation()
- api_token = M.ApiToken.query.get(user_id=c.user._id)
- return dict(
- menu=menu,
- api_token=api_token,
- )
+ return dict(menu=menu)
@h.vardec
@expose()
@@ -392,25 +388,6 @@ class PreferencesController(BaseController):
@expose()
@require_post()
- def gen_api_token(self):
- tok = M.ApiToken.query.get(user_id=c.user._id)
- if tok is None:
- tok = M.ApiToken(user_id=c.user._id)
- else:
- tok.secret_key = h.cryptographic_nonce()
- redirect(request.referer)
-
- @expose()
- @require_post()
- def del_api_token(self):
- tok = M.ApiToken.query.get(user_id=c.user._id)
- if tok is None:
- return
- tok.delete()
- redirect(request.referer)
-
- @expose()
- @require_post()
@validate(V.NullValidator(), error_handler=index)
def change_password(self, **kw):
kw = g.theme.password_change_form.to_python(kw, None)
http://git-wip-us.apache.org/repos/asf/allura/blob/65cc6e78/Allura/allura/templates/user_prefs.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_prefs.html b/Allura/allura/templates/user_prefs.html
index 25d1120..fbf47d8 100644
--- a/Allura/allura/templates/user_prefs.html
+++ b/Allura/allura/templates/user_prefs.html
@@ -106,29 +106,6 @@
</div>
{% endif %}
- {% if tg.config.get('auth.method', 'local') == 'local' %}
- <div class="grid-20">
- <h2>API Token</h2>
- {% if api_token %}
- <p>
- <b>API Key:</b><br/>
- {{api_token.api_key}}<br/>
- <b>Secret Key:</b><br/>
- {{api_token.secret_key}}<br/>
- </p>
- <form method="POST" action="del_api_token" class="grid-18">
- <input type="submit" value="Delete API Token">
- {{lib.csrf_token()}}
- </form>
- {% else %}
- <p>No API token generated</p>
- {% endif %}
- <form method="POST" action="gen_api_token" class="grid-18">
- <input type="submit" value="(Re)generate API Token">
- {{lib.csrf_token()}}
- </form>
- </div>
- {% endif %}
<div class="grid-20">
<h2>User Messages</h2>
<form method="POST" action="user_message">
[02/16] git commit: [#1687] ticket:574 Remove RestClient,
AlluraImportAPIClient, etc
Posted by br...@apache.org.
[#1687] ticket:574 Remove RestClient, AlluraImportAPIClient, etc
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/49f7e10b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/49f7e10b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/49f7e10b
Branch: refs/heads/master
Commit: 49f7e10b2da230baadd1336a27ab8781f58c8cdc
Parents: 44a7f5e
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 13:25:04 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:21 2014 +0000
----------------------------------------------------------------------
Allura/allura/lib/import_api.py | 69 ------
Allura/allura/lib/rest_api.py | 150 -------------
AlluraTest/alluratest/test_syntax.py | 1 -
.../forgetracker/scripts/import_tracker.py | 144 -------------
scripts/tracker-rip.py | 211 -------------------
5 files changed, 575 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/49f7e10b/Allura/allura/lib/import_api.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
deleted file mode 100644
index d8159c5..0000000
--- a/Allura/allura/lib/import_api.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import urllib
-import urllib2
-import urlparse
-import hmac
-import hashlib
-import json
-import logging
-from datetime import datetime
-
-log = logging.getLogger(__name__)
-
-
-class AlluraImportApiClient(object):
-
- def __init__(self, base_url, api_key, secret_key, verbose=False, retry=True):
- self.base_url = base_url
- self.api_key = api_key
- self.secret_key = secret_key
- self.verbose = verbose
- self.retry = retry
-
- def sign(self, path, params):
- params.append(('api_key', self.api_key))
- params.append(('api_timestamp', datetime.utcnow().isoformat()))
- message = path + '?' + urllib.urlencode(sorted(params))
- digest = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest()
- params.append(('api_signature', digest))
- return params
-
- def call(self, url, **params):
- url = urlparse.urljoin(self.base_url, url)
- if self.verbose:
- log.info("Import API URL: %s", url)
-
- params = self.sign(urlparse.urlparse(url).path, params.items())
-
- while True:
- try:
- result = urllib2.urlopen(url, urllib.urlencode(params))
- resp = result.read()
- return json.loads(resp)
- except urllib2.HTTPError, e:
- e.msg += ' ({0})'.format(url)
- if self.verbose:
- error_content = e.read()
- e.msg += '. Error response:\n' + error_content
- raise e
- except (urllib2.URLError, IOError):
- if self.retry:
- log.exception('Error making API request, will retry')
- continue
- raise
http://git-wip-us.apache.org/repos/asf/allura/blob/49f7e10b/Allura/allura/lib/rest_api.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/rest_api.py b/Allura/allura/lib/rest_api.py
deleted file mode 100644
index dcc0d7d..0000000
--- a/Allura/allura/lib/rest_api.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import hmac
-import json
-import hashlib
-import urllib
-import urllib2
-import logging
-from urlparse import urljoin, urlparse
-from datetime import datetime
-
-from tg.controllers.util import smart_str
-from formencode import variabledecode
-
-
-log = logging.getLogger(__name__)
-
-
-class RestClient(object):
-
- def __init__(self, api_key, secret_key, base_uri,
- http_username=None, http_password=None):
- self._api_key = api_key
- self._secret_key = secret_key
- self.base_uri = base_uri
- self.Request = self._request_class()
- self.RedirectHandler = self._redirect_handler_class()
- redirect_handler = self.RedirectHandler()
- if http_username:
- pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
- pw_mgr.add_password(None, base_uri, http_username, http_password)
- auth_handler = urllib2.HTTPBasicAuthHandler(pw_mgr)
- self._opener = urllib2.build_opener(redirect_handler, auth_handler)
- else:
- self._opener = urllib2.build_opener(redirect_handler)
-
- def sign_request(self, path, params):
- if hasattr(params, 'items'):
- params = params.items()
- has_api_key = has_api_timestamp = has_api_signature = False
- for k, v in params:
- if k == 'api_key':
- has_api_key = True
- if k == 'api_timestamp':
- has_api_timestamp = True
- if k == 'api_signature':
- has_api_signature = True
- if not has_api_key:
- params.append(('api_key', self._api_key))
- if not has_api_timestamp:
- params.append(('api_timestamp', datetime.utcnow().isoformat()))
- if not has_api_signature:
- string_to_sign = path + '?' + urlencode(sorted(params))
- digest = hmac.new(self._secret_key, string_to_sign, hashlib.sha256)
- params.append(('api_signature', digest.hexdigest()))
- return params
-
- def request(self, method, path, **params):
- req = self.Request(method, path, params)
- fp = self._opener.open(req)
- return json.loads(fp.read())
-
- def _redirect_handler_class(self):
- client = self
-
- class RedirectHandler(urllib2.HTTPRedirectHandler):
-
- def redirect_request(self, req, fp, code, msg, headers, newurl):
- m = req.get_method()
- if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
- or code in (301, 302, 303) and m == "POST"):
- newurl = newurl.replace(' ', '%20')
- newheaders = dict((k, v) for k, v in req.headers.items()
- if k.lower() not in ("content-length", "content-type")
- )
- result = urlparse(newurl)
- log.debug('Redirect to %s' % result.path)
- return client.Request(
- 'GET', result.path,
- headers=newheaders,
- origin_req_host=req.get_origin_req_host(),
- unverifiable=True)
- else:
- raise urllib2.HTTPError(
- req.get_full_url(), code, msg, headers, fp)
- return RedirectHandler
-
- def _request_class(self):
- client = self
-
- class Request(urllib2.Request):
-
- def __init__(self, method, path, params=None, **kwargs):
- if params is None:
- params = {}
- params = variabledecode.variable_encode(
- params, add_repetitions=False)
- params = client.sign_request(path, params)
- self._method = method.upper()
- if self._method == 'GET':
- url = urljoin(client.base_uri, path) + \
- '?' + urlencode(params)
- data = None
- else:
- url = urljoin(client.base_uri, path)
- data = urlencode(params)
- urllib2.Request.__init__(self, url, data=data, **kwargs)
-
- def get_method(self):
- return self._method
- return Request
-
-
-def generate_smart_str(params):
- if isinstance(params, dict):
- iterparams = params.iteritems()
- else:
- iterparams = iter(params)
- for key, value in iterparams:
- if value is None:
- continue
- if isinstance(value, (list, tuple)):
- for item in value:
- yield smart_str(key), smart_str(item)
- else:
- yield smart_str(key), smart_str(value)
-
-
-def urlencode(params):
- """
- A version of Python's urllib.urlencode() function that can operate on
- unicode strings. The parameters are first case to UTF-8 encoded strings and
- then encoded as per normal.
- """
- return urllib.urlencode([i for i in generate_smart_str(params)])
http://git-wip-us.apache.org/repos/asf/allura/blob/49f7e10b/AlluraTest/alluratest/test_syntax.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index c782aac..b30a6b8 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -94,7 +94,6 @@ def test_no_prints():
'Allura/ez_setup/',
'Allura/allura/lib/AsciiDammit.py',
'/scripts/',
- 'Allura/allura/lib/import_api.py',
'ForgeSVN/setup.py',
]
if run(find_py + " | grep -v '" + "' | grep -v '".join(skips) + "' | xargs grep -v '^ *#' | grep 'print ' | grep -E -v '(pprint|#pragma: ?printok)' ") != 1:
http://git-wip-us.apache.org/repos/asf/allura/blob/49f7e10b/ForgeTracker/forgetracker/scripts/import_tracker.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/scripts/import_tracker.py b/ForgeTracker/forgetracker/scripts/import_tracker.py
deleted file mode 100644
index c991d11..0000000
--- a/ForgeTracker/forgetracker/scripts/import_tracker.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-
-import argparse
-import json
-import logging
-
-from allura.scripts import ScriptTask
-from allura.lib.import_api import AlluraImportApiClient
-
-log = logging.getLogger(__name__)
-
-
-def import_tracker(cli, project, tool, import_options, doc_txt,
- validate=True, verbose=False, cont=False, neighborhood='p'):
- url = '/rest/{neighborhood}/{project}/{tool}'.format(
- neighborhood=neighborhood,
- project=project,
- tool=tool,
- )
- if validate:
- url += '/validate_import'
- else:
- url += '/perform_import'
-
- existing_map = {}
- if cont:
- existing_tickets = cli.call(url + '/')['tickets']
- for t in existing_tickets:
- existing_map[t['ticket_num']] = t['summary']
-
- doc = json.loads(doc_txt)
-
- if 'trackers' in doc and 'default' in doc['trackers'] and 'artifacts' in doc['trackers']['default']:
- tickets_in = doc['trackers']['default']['artifacts']
- doc['trackers']['default']['artifacts'] = []
- else:
- tickets_in = doc
-
- if verbose:
- print "Processing %d tickets" % len(tickets_in)
-
- for cnt, ticket_in in enumerate(tickets_in):
- if ticket_in['id'] in existing_map:
- if verbose:
- print 'Ticket id %d already exists, skipping' % ticket_in['id']
- continue
- doc_import = {}
- doc_import['trackers'] = {}
- doc_import['trackers']['default'] = {}
- doc_import['trackers']['default']['artifacts'] = [ticket_in]
- res = cli.call(url, doc=json.dumps(doc_import),
- options=json.dumps(import_options))
- assert res['status'] and not res['errors'], res['errors']
- if validate:
- if res['warnings']:
- print "Ticket id %s warnings: %s" % (ticket_in['id'], res['warnings'])
- else:
- print "Imported ticket id %s" % (ticket_in['id'])
-
-
-class ImportTracker(ScriptTask):
-
- @classmethod
- def execute(cls, options):
- user_map = {}
- import_options = {}
- for s in options.import_opts:
- k, v = s.split('=', 1)
- if v == 'false':
- v = False
- import_options[k] = v
-
- if options.user_map_file:
- f = open(options.user_map_file)
- try:
- user_map = json.load(f)
- if type(user_map) is not type({}):
- raise ValueError
- for k, v in user_map.iteritems():
- if not isinstance(k, basestring) or not isinstance(v, basestring):
- raise ValueError
- except ValueError:
- raise '--user-map should specify JSON file with format {"original_user": "sf_user", ...}'
- finally:
- f.close()
- import_options['user_map'] = user_map
- cli = AlluraImportApiClient(
- options.base_url, options.api_key, options.secret_key, options.verbose)
- doc_txt = open(options.file_data).read()
- import_tracker(
- cli, options.project, options.tracker, import_options, doc_txt,
- validate=options.validate,
- verbose=options.verbose,
- cont=options.cont)
-
- @classmethod
- def parser(cls):
- parser = argparse.ArgumentParser(
- description='import tickets from json')
- parser.add_argument('--nbhd', action='store', default='', dest='nbhd',
- help='Restrict update to a particular neighborhood, e.g. /p/.')
- parser.add_argument('-a', '--api-ticket',
- action='store', dest='api_key', help='API ticket')
- parser.add_argument('-s', '--secret-key', action='store',
- dest='secret_key', help='Secret key')
- parser.add_argument('-p', '--project', action='store',
- dest='project', help='Project to import to')
- parser.add_argument('-t', '--tracker', action='store',
- dest='tracker', help='Tracker to import to')
- parser.add_argument('-u', '--base-url', dest='base_url',
- default='https://sourceforge.net', help='Base Allura URL (https://sourceforge.net)')
- parser.add_argument('-o', dest='import_opts',
- default=[], action='store', help='Specify import option(s)', metavar='opt=val')
- parser.add_argument('--user-map', dest='user_map_file',
- help='Map original users to SF.net users', metavar='JSON_FILE')
- parser.add_argument('--file_data', dest='file_data',
- help='json file', metavar='JSON_FILE')
- parser.add_argument('--validate', dest='validate',
- action='store_true', help='Validate import data')
- parser.add_argument('-v', '--verbose', dest='verbose',
- action='store_true', help='Verbose operation')
- parser.add_argument('-c', '--continue', dest='cont',
- action='store_true', help='Continue import into existing tracker')
- return parser
-
-
-if __name__ == '__main__':
- ImportTracker.main()
http://git-wip-us.apache.org/repos/asf/allura/blob/49f7e10b/scripts/tracker-rip.py
----------------------------------------------------------------------
diff --git a/scripts/tracker-rip.py b/scripts/tracker-rip.py
deleted file mode 100755
index aeef1eb..0000000
--- a/scripts/tracker-rip.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/python
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import getpass
-from urlparse import urljoin
-
-from allura.lib import rest_api
-
-SRC_CRED = dict(
- api_key='c03efc6cca1cf78be9e9',
- secret_key='575eda2f25f6490d8cfe5d02f2506c010112894d0ea10660e43157a87a7e620c61ac06397b028af1',
- http_username=raw_input('LDAP username: '),
- http_password=getpass.getpass('LDAP password: '))
-SRC_SERVER = 'https://newforge.sf.geek.net/'
-SRC_TOOL = '/rest/p/forge/tickets/'
-
-# Credentials for sf-overlords
-# DST_CRED=dict(
-# api_key='a4a88c67179137053d70',
-# secret_key='fcc48a0c31459e99a88cc42cdd7f908fad78b283ca30a86caac1ab65036ff71fc195a18e56534dc5')
-# DST_SERVER='http://sourceforge.net/'
-# DST_TOOL='/rest/p/allura/tickets/'
-DST_CRED = dict(
- api_key='aa7244645424513d9636',
- secret_key='cd1d97be98497f7b615b297aa2061177ddf6d42b95a8484193f84690486694234dbf817efc3b2d6e')
-DST_SERVER = 'http://localhost:8080/'
-DST_TOOL = '/rest/p/test/bugs/'
-
-FAKE_TICKET = {
- u'created_date': u'2010-03-08 17:29:42.802000',
- u'assigned_to_id': u'',
- u'assigned_to': u'',
- u'custom_fields': {'_component': '', '_size': 0, '_priority': '', '_type': ''},
- u'description': u'Ticket was not present in source',
- u'milestone': u'',
- u'reported_by': u'',
- u'reported_by_id': u'',
- u'status': u'closed',
- u'sub_ids': [],
- u'summary': u'Placeholder ticket',
- u'super_id': u'None'}
-
-
-def main():
- src_cli = rest_api.RestClient(
- base_uri=SRC_SERVER,
- **SRC_CRED)
- dst_cli = rest_api.RestClient(
- base_uri=DST_SERVER,
- **DST_CRED)
- src = TicketAPI(src_cli, SRC_TOOL)
- dst = TicketAPI(dst_cli, DST_TOOL)
- for ticket in src.iter_tickets(min_ticket=3, check=True):
- print 'Migrating ticket %s:\n%s' % (ticket['ticket_num'], ticket)
- print 'Create ticket on %s' % DST_SERVER
- dst.create_ticket(ticket)
- print 'Create discussion on %s' % DST_SERVER
- src_thread = src.load_thread(ticket)
- if not src_thread or not src_thread['posts']:
- print '... no posts'
- continue
- dst_thread = dst.load_thread(ticket)
- slug_map = {}
- for post in src.iter_posts(src_thread):
- print '... migrate post %s:\n%r' % (post['slug'], post['text'])
- dst.create_post(dst_thread, post, slug_map)
-
-
-class TicketAPI(object):
-
- def __init__(self, client, path):
- self.client = client
- self.path = path
-
- def iter_tickets(self, min_ticket=1, max_ticket=None, check=False):
- if check:
- tickets = self.client.request('GET', self.path)['tickets']
- valid_tickets = set(t['ticket_num'] for t in tickets)
- max_valid_ticket = max(valid_tickets)
- cur_ticket = min_ticket
- while True:
- if check and cur_ticket not in valid_tickets:
- if cur_ticket > max_valid_ticket:
- break
- yield dict(FAKE_TICKET, ticket_num=cur_ticket)
- cur_ticket += 1
- continue
- ticket = self.client.request(
- 'GET', self.ticket_path(cur_ticket))['ticket']
- if ticket is None:
- break
- yield ticket
- cur_ticket += 1
- if max_ticket and cur_ticket > max_ticket:
- break
-
- def load_thread(self, ticket):
- discussion = self.client.request(
- 'GET', self.discussion_path())['discussion']
- for thd in discussion['threads']:
- if thd['subject'].startswith('#%d ' % ticket['ticket_num']):
- break
- else:
- return None
- thread = self.client.request(
- 'GET', self.thread_path(thd['_id']))['thread']
- return thread
-
- def iter_posts(self, thread):
- for p in sorted(thread['posts'], key=lambda p: p['slug']):
- post = self.client.request(
- 'GET', self.post_path(thread['_id'], p['slug']))['post']
- yield post
-
- def create_ticket(self, ticket):
- ticket = dict(ticket, labels='')
- ticket['description'] = 'Created by: %s\nCreated date: %s\nAssigned to:%s\n\n%s' % (
- ticket['reported_by'], ticket['created_date'], ticket['assigned_to'], ticket['description'])
- for bad_key in ('assigned_to_id', 'created_date', 'reported_by', 'reported_by_id', 'super_id', 'sub_ids', '_id'):
- if bad_key in ticket:
- del ticket[bad_key]
- ticket.setdefault('labels', '')
- ticket['custom_fields'].setdefault('_size', 0)
- ticket['custom_fields'].setdefault('_priority', 'low')
- ticket['custom_fields'].setdefault('_type', 'Bug')
- ticket['custom_fields'].setdefault('_type', 'Component')
- if ticket['custom_fields']['_size'] is None:
- ticket['custom_fields']['_size'] = 0
- if ticket['milestone'] not in ('backlog', 'public2', 'GA', 'post-GA'):
- ticket['milestone'] = ''
- if ticket['status'] not in 'open in-progress code-review validation closed'.split():
- ticket['status'] = 'open'
- r = self.client.request(
- 'POST', self.new_ticket_path(), ticket_form=ticket)
- self.client.request(
- 'POST', self.ticket_path(r['ticket']['ticket_num'], 'save'),
- ticket_form=ticket)
-
- def create_post(self, thread, post, slug_map):
- text = 'Post by %s:\n%s' % (
- post['author'], post['text'])
- if '/' in post['slug']:
- parent_post = slug_map[post['slug'].rsplit('/', 1)[0]]
- new_post = self.client.request(
- 'POST', self.post_path(thread['_id'], parent_post, 'reply'),
- text=text)['post']
- else:
- new_post = self.client.request(
- 'POST', self.thread_path(thread['_id'], 'new'),
- text=text)['post']
- slug_map[post['slug']] = new_post['slug']
- return new_post
-
- def new_ticket_path(self):
- return urljoin(self.path, 'new')
-
- def ticket_path(self, ticket_num, suffix=''):
- return urljoin(self.path, str(ticket_num)) + '/' + suffix
-
- def discussion_path(self):
- return '%s_discuss/' % (self.path)
-
- def thread_path(self, thread_id, suffix=''):
- return '%s_discuss/thread/%s/%s' % (self.path, thread_id, suffix)
-
- def post_path(self, thread_id, post_slug, suffix=''):
- return '%s_discuss/thread/%s/%s/%s' % (self.path, thread_id, post_slug, suffix)
-
-
-def pm(etype, value, tb): # pragma no cover
- import pdb
- import traceback
- try:
- from IPython.ipapi import make_session
- make_session()
- from IPython.Debugger import Pdb
- sys.stderr.write('Entering post-mortem IPDB shell\n')
- p = Pdb(color_scheme='Linux')
- p.reset()
- p.setup(None, tb)
- p.print_stack_trace()
- sys.stderr.write('%s: %s\n' % (etype, value))
- p.cmdloop()
- p.forget()
- # p.interaction(None, tb)
- except ImportError:
- sys.stderr.write('Entering post-mortem PDB shell\n')
- traceback.print_exception(etype, value, tb)
- pdb.post_mortem(tb)
-
-sys.excepthook = pm
-
-if __name__ == '__main__':
- main()
[11/16] git commit: [#1687] ticket:574 Remove/fix tests in Allura core
Posted by br...@apache.org.
[#1687] ticket:574 Remove/fix tests in Allura core
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5b0522b1
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5b0522b1
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5b0522b1
Branch: refs/heads/master
Commit: 5b0522b1f328ad4ac0f5b0e51a96410fe6c714c1
Parents: 7b65cf2
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 17:14:37 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
Allura/allura/tests/functional/test_auth.py | 12 ---
Allura/allura/tests/functional/test_rest.py | 31 ++-----
.../tests/functional/test_rest_api_tickets.py | 87 --------------------
Allura/allura/tests/model/test_auth.py | 17 ----
4 files changed, 6 insertions(+), 141 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/5b0522b1/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 0d4f8f7..f35f5f1 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -196,18 +196,6 @@ class TestAuth(TestController):
r = self.app.get('/auth/subscriptions/')
assert '<option selected value="both">Combined</option>' in r
- def test_api_key(self):
- r = self.app.get('/auth/preferences/')
- assert 'No API token generated' in r
- r = self.app.post('/auth/preferences/gen_api_token', status=302)
- r = self.app.get('/auth/preferences/')
- assert 'No API token generated' not in r
- assert 'API Key:' in r
- assert 'Secret Key:' in r
- r = self.app.post('/auth/preferences/del_api_token', status=302)
- r = self.app.get('/auth/preferences/')
- assert 'No API token generated' in r
-
def test_create_account(self):
r = self.app.get('/auth/create_account')
assert 'Create an Account' in r
http://git-wip-us.apache.org/repos/asf/allura/blob/5b0522b1/Allura/allura/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index 83889c1..51ae930 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -17,8 +17,6 @@
# specific language governing permissions and limitations
# under the License.
-from datetime import datetime, timedelta
-
from pylons import app_globals as g
import mock
from nose.tools import assert_equal, assert_in, assert_not_in
@@ -30,38 +28,20 @@ from allura.lib import helpers as h
from allura.lib.exceptions import Invalid
from allura import model as M
-from forgetracker.tracker_main import ForgeTrackerApp
-
class TestRestHome(TestRestApiBase):
- def test_bad_signature(self):
- r = self.api_post('/rest/p/test/wiki/', api_signature='foo')
- assert r.status_int == 403
-
- def test_bad_token(self):
- r = self.api_post('/rest/p/test/wiki/', api_key='foo')
- assert r.status_int == 403
-
- def test_bad_timestamp(self):
- r = self.api_post('/rest/p/test/wiki/',
- api_timestamp=(datetime.utcnow() + timedelta(days=1)).isoformat())
- assert r.status_int == 403
-
- @mock.patch('allura.controllers.rest.M.OAuthAccessToken')
- @mock.patch('allura.controllers.rest.request')
- def test_bearer_token_non_ssl(self, request, OAuthAccessToken):
- request.params = {'access_token': 'foo'}
- request.scheme = 'http'
- r = self.api_post('/rest/p/test/wiki', access_token='foo')
- assert_equal(r.status_int, 403)
- assert_equal(OAuthAccessToken.query.get.call_count, 0)
+ def _patch_token(self, OAuthAccessToken):
+ at = OAuthAccessToken.return_value
+ at.__ming__ = mock.MagicMock()
+ at.api_key = 'foo'
@mock.patch('allura.controllers.rest.M.OAuthAccessToken')
@mock.patch('allura.controllers.rest.request')
def test_bearer_token_non_bearer(self, request, OAuthAccessToken):
request.params = {'access_token': 'foo'}
request.scheme = 'https'
+ self._patch_token(OAuthAccessToken)
access_token = OAuthAccessToken.query.get.return_value
access_token.is_bearer = False
r = self.api_post('/rest/p/test/wiki', access_token='foo')
@@ -73,6 +53,7 @@ class TestRestHome(TestRestApiBase):
def test_bearer_token_invalid(self, request, OAuthAccessToken):
request.params = {'access_token': 'foo'}
request.scheme = 'https'
+ self._patch_token(OAuthAccessToken)
OAuthAccessToken.query.get.return_value = None
r = self.api_post('/rest/p/test/wiki', access_token='foo')
assert_equal(r.status_int, 403)
http://git-wip-us.apache.org/repos/asf/allura/blob/5b0522b1/Allura/allura/tests/functional/test_rest_api_tickets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest_api_tickets.py b/Allura/allura/tests/functional/test_rest_api_tickets.py
deleted file mode 100644
index 8185d5d..0000000
--- a/Allura/allura/tests/functional/test_rest_api_tickets.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-from datetime import datetime, timedelta
-
-from ming.orm import session
-
-from allura import model as M
-from allura.tests import decorators as td
-from alluratest.controller import TestRestApiBase
-
-
-class TestApiTicket(TestRestApiBase):
-
- def set_api_ticket(self, expire=None):
- if not expire:
- expire = timedelta(days=1)
- test_admin = M.User.query.get(username='test-admin')
- api_ticket = M.ApiTicket(
- user_id=test_admin._id, capabilities={
- 'import': ['Projects', 'test']},
- expires=datetime.utcnow() + expire)
- session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- def test_bad_signature(self):
- self.set_api_ticket()
- r = self.api_post('/rest/p/test/wiki/', api_signature='foo')
- assert r.status_int == 403
-
- def test_bad_token(self):
- self.set_api_ticket()
- r = self.api_post('/rest/p/test/wiki/', api_key='foo')
- assert r.status_int == 403
-
- def test_bad_timestamp(self):
- self.set_api_ticket()
- r = self.api_post('/rest/p/test/wiki/',
- api_timestamp=(datetime.utcnow() + timedelta(days=1)).isoformat())
- assert r.status_int == 403
-
- def test_bad_path(self):
- self.set_api_ticket()
- r = self.api_post('/rest/1/test/wiki/')
- assert r.status_int == 404
- r = self.api_post('/rest/p/1223/wiki/')
- assert r.status_int == 404
- r = self.api_post('/rest/p/test/12wiki/')
- assert r.status_int == 404
-
- def test_no_api(self):
- self.set_api_ticket()
- r = self.api_post('/rest/p/test/admin/')
- assert r.status_int == 404
-
- @td.with_wiki
- def test_project_ping(self):
- self.set_api_ticket()
- r = self.api_get('/rest/p/test/wiki/Home/')
- assert r.status_int == 200
- assert r.json['title'] == 'Home', r.json
-
- def test_project_ping_expired_ticket(self):
- self.set_api_ticket(timedelta(seconds=-1))
- r = self.api_post('/rest/p/test/wiki/')
- assert r.status_int == 403
-
- @td.with_tool('test/sub1', 'Wiki', 'wiki')
- def test_subproject_ping(self):
- self.set_api_ticket()
- r = self.api_get('/rest/p/test/sub1/wiki/Home/')
- assert r.status_int == 200
- assert r.json['title'] == 'Home', r.json
http://git-wip-us.apache.org/repos/asf/allura/blob/5b0522b1/Allura/allura/tests/model/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 1c76611..35f056e 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -173,23 +173,6 @@ def test_default_project_roles():
@with_setup(setUp)
-def test_dup_api_token():
- from ming.orm import session
- u = M.User.register(dict(username='nosetest-user'))
- ThreadLocalORMSession.flush_all()
- tok = M.ApiToken(user_id=u._id)
- session(tok).flush()
- tok2 = M.ApiToken(user_id=u._id)
- try:
- session(tok2).flush()
- assert False, "Entry with duplicate unique key was inserted"
- except DuplicateKeyError:
- pass
- assert len(M.ApiToken.query.find().all()
- ) == 1, "Duplicate entries with unique key found"
-
-
-@with_setup(setUp)
def test_email_address_claimed_by_user():
addr = M.EmailAddress(_id='test_admin@domain.net',
claimed_by_user_id=c.user._id)
[07/16] git commit: [#1687] ticket:582 Add upsert to
OAuthConsumerToken
Posted by br...@apache.org.
[#1687] ticket:582 Add upsert to OAuthConsumerToken
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/66753ddc
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/66753ddc
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/66753ddc
Branch: refs/heads/master
Commit: 66753ddc4c6cee448d4710d766543c937e03e0f6
Parents: d178196
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue May 6 14:26:36 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
Allura/allura/model/oauth.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/66753ddc/Allura/allura/model/oauth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/oauth.py b/Allura/allura/model/oauth.py
index 14b30d1..fd250bb 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -20,7 +20,9 @@ import logging
import oauth2 as oauth
from pylons import tmpl_context as c, app_globals as g
+import pymongo
from ming import schema as S
+from ming.orm import session
from ming.orm import FieldProperty, RelationProperty, ForeignIdProperty
from ming.orm.declarative import MappedClass
@@ -68,6 +70,19 @@ class OAuthConsumerToken(OAuthToken):
user = RelationProperty('User')
+ @classmethod
+ def upsert(cls, name):
+ t = cls.query.get(name=name)
+ if t is not None:
+ return t
+ try:
+ t = cls(name=name)
+ session(t).flush(t)
+ except pymongo.errors.DuplicateKeyError:
+ session(t).expunge(t)
+ t = cls.query.get(name=name)
+ return t
+
@property
def description_html(self):
return g.markdown.cached_convert(self, 'description')
[13/16] git commit: Revert "[#1687] ticket:582 Don't check
capabilities in discussion import"
Posted by br...@apache.org.
Revert "[#1687] ticket:582 Don't check capabilities in discussion import"
This reverts commit 8f53750ad841cadfc1d8c7a3b3f098339606589f.
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/0f99ab73
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/0f99ab73
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/0f99ab73
Branch: refs/heads/master
Commit: 0f99ab7325441a56c677dd11595ad0de70519aab
Parents: acabd59
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed May 28 12:45:28 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:23 2014 +0000
----------------------------------------------------------------------
AlluraTest/alluratest/controller.py | 3 +-
.../forgediscussion/controllers/root.py | 4 ++
.../tests/functional/test_import.py | 40 ++++++++++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/0f99ab73/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 433431f..57d0fe4 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -197,7 +197,8 @@ class TestRestApiBase(TestController):
consumer_token_id=consumer_token._id,
user_id=user._id,
callback='manual',
- validation_pin=h.nonce(20))
+ validation_pin=h.nonce(20),
+ is_bearer=True)
token = M.OAuthAccessToken(
consumer_token_id=consumer_token._id,
request_token_id=request_token._id,
http://git-wip-us.apache.org/repos/asf/allura/blob/0f99ab73/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 7002109..b315dca 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -349,6 +349,10 @@ class RootRestController(BaseController):
require_access(c.project, 'admin')
if username_mapping is None:
username_mapping = '{}'
+ if c.api_token.get_capability('import') != [c.project.neighborhood.name, c.project.shortname]:
+ log.error('Import capability is not enabled for %s',
+ c.project.shortname)
+ raise exc.HTTPForbidden(detail='Import is not allowed')
try:
doc = json.loads(doc)
username_mapping = json.loads(username_mapping)
http://git-wip-us.apache.org/repos/asf/allura/blob/0f99ab73/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index b4f4158..deeb349 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -35,12 +35,34 @@ class TestImportController(TestRestApiBase): # TestController):
self.app.get('/discussion/')
self.json_text = open(here_dir + '/data/sf.json').read()
+ def test_no_capability(self):
+ self.set_api_ticket({'import2': ['Projects', 'test']})
+ resp = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert resp.status_int == 403
+
+ self.set_api_ticket({'import': ['Projects', 'test2']})
+ resp = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert resp.status_int == 403
+
+ self.set_api_ticket({'import': ['Projects', 'test']})
+ resp = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert resp.status_int == 200
+
def test_validate_import(self):
r = self.api_post('/rest/p/test/discussion/validate_import',
doc=self.json_text)
assert not r.json['errors']
def test_import_anon(self):
+ api_ticket = M.ApiTicket(
+ user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
+ expires=datetime.utcnow() + timedelta(days=1))
+ ming.orm.session(api_ticket).flush()
+ self.set_api_token(api_ticket)
+
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text)
assert not r.json['errors'], r.json['errors']
@@ -56,6 +78,12 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' in str(r)
def test_import_map(self):
+ api_ticket = M.ApiTicket(
+ user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
+ expires=datetime.utcnow() + timedelta(days=1))
+ ming.orm.session(api_ticket).flush()
+ self.set_api_token(api_ticket)
+
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text,
username_mapping=json.dumps(dict(rick446='test-user')))
@@ -73,6 +101,12 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' not in str(r)
def test_import_create(self):
+ api_ticket = M.ApiTicket(
+ user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
+ expires=datetime.utcnow() + timedelta(days=1))
+ ming.orm.session(api_ticket).flush()
+ self.set_api_token(api_ticket)
+
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text, create_users='True')
assert not r.json['errors'], r.json['errors']
@@ -88,6 +122,12 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' not in str(r)
assert 'test-rick446' in str(r)
+ def set_api_ticket(self, caps={'import': ['Projects', 'test']}):
+ api_ticket = M.ApiTicket(user_id=c.user._id, capabilities=caps,
+ expires=datetime.utcnow() + timedelta(days=1))
+ ming.orm.session(api_ticket).flush()
+ self.set_api_token(api_ticket)
+
@staticmethod
def time_normalize(t):
return t.replace('T', ' ').replace('Z', '')
[10/16] git commit: [#1687] ticket:582 Use oauth bearer tokens for
AlluraImportApiClient
Posted by br...@apache.org.
[#1687] ticket:582 Use oauth bearer tokens for AlluraImportApiClient
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d1781962
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d1781962
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d1781962
Branch: refs/heads/master
Commit: d178196291fdfe232c561c8e1de8d5389f407f34
Parents: 5b0522b
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue May 6 12:32:06 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
Allura/allura/lib/import_api.py | 64 ++++++++++++++++++++++
ForgeTracker/forgetracker/scripts/__init__.py | 16 ------
scripts/allura_import.py | 30 +++-------
3 files changed, 73 insertions(+), 37 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/d1781962/Allura/allura/lib/import_api.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
new file mode 100644
index 0000000..60754a6
--- /dev/null
+++ b/Allura/allura/lib/import_api.py
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import urllib
+import urllib2
+import urlparse
+import hmac
+import hashlib
+import json
+import logging
+from datetime import datetime
+
+log = logging.getLogger(__name__)
+
+
+class AlluraImportApiClient(object):
+
+ def __init__(self, base_url, token, verbose=False, retry=True):
+ self.base_url = base_url
+ self.token = token
+ self.verbose = verbose
+ self.retry = retry
+
+ def sign(self, path, params):
+ params.append(('access_token', self.token))
+ return params
+
+ def call(self, url, **params):
+ url = urlparse.urljoin(self.base_url, url)
+ if self.verbose:
+ log.info("Import API URL: %s", url)
+
+ params = self.sign(urlparse.urlparse(url).path, params.items())
+
+ while True:
+ try:
+ result = urllib2.urlopen(url, urllib.urlencode(params))
+ resp = result.read()
+ return json.loads(resp)
+ except urllib2.HTTPError, e:
+ e.msg += ' ({0})'.format(url)
+ if self.verbose:
+ error_content = e.read()
+ e.msg += '. Error response:\n' + error_content
+ raise e
+ except (urllib2.URLError, IOError):
+ if self.retry:
+ log.exception('Error making API request, will retry')
+ continue
+ raise
http://git-wip-us.apache.org/repos/asf/allura/blob/d1781962/ForgeTracker/forgetracker/scripts/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/scripts/__init__.py b/ForgeTracker/forgetracker/scripts/__init__.py
deleted file mode 100644
index 144e298..0000000
--- a/ForgeTracker/forgetracker/scripts/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
http://git-wip-us.apache.org/repos/asf/allura/blob/d1781962/scripts/allura_import.py
----------------------------------------------------------------------
diff --git a/scripts/allura_import.py b/scripts/allura_import.py
index 270d988..d4e51fd 100644
--- a/scripts/allura_import.py
+++ b/scripts/allura_import.py
@@ -19,7 +19,6 @@ import json
from optparse import OptionParser
from allura.lib.import_api import AlluraImportApiClient
-from forgetracker.scripts.import_tracker import import_tracker
from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki
@@ -52,22 +51,15 @@ def main():
import_options['user_map'] = user_map
- cli = AlluraImportApiClient(
- options.base_url, options.api_key, options.secret_key, options.verbose)
+ cli = AlluraImportApiClient(options.base_url, options.token, options.verbose)
doc_txt = open(args[0]).read()
- # import the tracker (if any)
- if options.tracker:
- import_tracker(
- cli, options.project, options.tracker, import_options, options, doc_txt,
- validate=options.validate, verbose=options.verbose,
- neighborhood=options.neighborhood)
- elif options.forum:
+ if options.forum:
import_forum(cli, options.project, options.forum, user_map, doc_txt,
- validate=options.validate, neighborhood=options.neighborhood)
+ validate=options.validate, neighborhood=options.neighborhood)
elif options.wiki:
- import_wiki(cli, options.project, options.wiki, options, doc_txt,
- neighborhood=options.neighborhood)
+ import_wiki(cli, options.project, options.wiki, options, doc_txt)
+
def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
@@ -89,17 +81,13 @@ def parse_options():
optparser = OptionParser(usage='''%prog [options] <JSON dump>
Import project data dump in JSON format into an Allura project.''')
- optparser.add_option('-a', '--api-ticket',
- dest='api_key', help='API ticket')
- optparser.add_option('-s', '--secret-key',
- dest='secret_key', help='Secret key')
+ optparser.add_option('-t', '--token', dest='token',
+ help='OAuth bearer token (generate at /auth/oauth/)')
optparser.add_option('-p', '--project', dest='project',
help='Project to import to')
optparser.add_option('-n', '--neighborhood', dest='neighborhood',
help="URL prefix of destination neighborhood (default is 'p')",
default='p')
- optparser.add_option('-t', '--tracker', dest='tracker',
- help='Tracker to import to')
optparser.add_option('-f', '--forum', dest='forum',
help='Forum tool to import to')
optparser.add_option('-w', '--wiki', dest='wiki',
@@ -119,8 +107,8 @@ Import project data dump in JSON format into an Allura project.''')
options, args = optparser.parse_args()
if len(args) != 1:
optparser.error("Wrong number of arguments")
- if not options.api_key or not options.secret_key:
- optparser.error("Keys are required")
+ if not options.token:
+ optparser.error("OAuth bearer token is required")
if not options.project:
optparser.error("Target project is required")
options.neighborhood = options.neighborhood.strip('/')
[14/16] git commit: [#1687] ticket:582 Don't check capabilities in
discussion import
Posted by br...@apache.org.
[#1687] ticket:582 Don't check capabilities in discussion import
Since OAuth authentication scheme doesn't support it.
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/acabd593
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/acabd593
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/acabd593
Branch: refs/heads/master
Commit: acabd593561e9190da51d84117c69b30ece0399c
Parents: 19a50da
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue May 6 15:49:38 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:23 2014 +0000
----------------------------------------------------------------------
AlluraTest/alluratest/controller.py | 3 +-
.../forgediscussion/controllers/root.py | 4 --
.../tests/functional/test_import.py | 40 --------------------
3 files changed, 1 insertion(+), 46 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/acabd593/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 57d0fe4..433431f 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -197,8 +197,7 @@ class TestRestApiBase(TestController):
consumer_token_id=consumer_token._id,
user_id=user._id,
callback='manual',
- validation_pin=h.nonce(20),
- is_bearer=True)
+ validation_pin=h.nonce(20))
token = M.OAuthAccessToken(
consumer_token_id=consumer_token._id,
request_token_id=request_token._id,
http://git-wip-us.apache.org/repos/asf/allura/blob/acabd593/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index b315dca..7002109 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -349,10 +349,6 @@ class RootRestController(BaseController):
require_access(c.project, 'admin')
if username_mapping is None:
username_mapping = '{}'
- if c.api_token.get_capability('import') != [c.project.neighborhood.name, c.project.shortname]:
- log.error('Import capability is not enabled for %s',
- c.project.shortname)
- raise exc.HTTPForbidden(detail='Import is not allowed')
try:
doc = json.loads(doc)
username_mapping = json.loads(username_mapping)
http://git-wip-us.apache.org/repos/asf/allura/blob/acabd593/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index deeb349..b4f4158 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -35,34 +35,12 @@ class TestImportController(TestRestApiBase): # TestController):
self.app.get('/discussion/')
self.json_text = open(here_dir + '/data/sf.json').read()
- def test_no_capability(self):
- self.set_api_ticket({'import2': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 403
-
- self.set_api_ticket({'import': ['Projects', 'test2']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 403
-
- self.set_api_ticket({'import': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 200
-
def test_validate_import(self):
r = self.api_post('/rest/p/test/discussion/validate_import',
doc=self.json_text)
assert not r.json['errors']
def test_import_anon(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text)
assert not r.json['errors'], r.json['errors']
@@ -78,12 +56,6 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' in str(r)
def test_import_map(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text,
username_mapping=json.dumps(dict(rick446='test-user')))
@@ -101,12 +73,6 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' not in str(r)
def test_import_create(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
r = self.api_post('/rest/p/test/discussion/perform_import',
doc=self.json_text, create_users='True')
assert not r.json['errors'], r.json['errors']
@@ -122,12 +88,6 @@ class TestImportController(TestRestApiBase): # TestController):
assert 'Anonymous' not in str(r)
assert 'test-rick446' in str(r)
- def set_api_ticket(self, caps={'import': ['Projects', 'test']}):
- api_ticket = M.ApiTicket(user_id=c.user._id, capabilities=caps,
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
@staticmethod
def time_normalize(t):
return t.replace('T', ' ').replace('Z', '')
[16/16] git commit: [#1687] ticket:589 Add back fix for token
creation in tests after revert
Posted by br...@apache.org.
[#1687] ticket:589 Add back fix for token creation in tests after revert
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2392ea7f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2392ea7f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2392ea7f
Branch: refs/heads/master
Commit: 2392ea7f620437418efd62063fb5b91d95b4bd6f
Parents: 0f99ab7
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed May 28 12:46:46 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:23 2014 +0000
----------------------------------------------------------------------
AlluraTest/alluratest/controller.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/2392ea7f/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 57d0fe4..433431f 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -197,8 +197,7 @@ class TestRestApiBase(TestController):
consumer_token_id=consumer_token._id,
user_id=user._id,
callback='manual',
- validation_pin=h.nonce(20),
- is_bearer=True)
+ validation_pin=h.nonce(20))
token = M.OAuthAccessToken(
consumer_token_id=consumer_token._id,
request_token_id=request_token._id,
[09/16] git commit: [#1687] ticket:574 Fix DuplicateKeyError while
creating oauth tokens in tests
Posted by br...@apache.org.
[#1687] ticket:574 Fix DuplicateKeyError while creating oauth tokens in tests
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/506d4d01
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/506d4d01
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/506d4d01
Branch: refs/heads/master
Commit: 506d4d017a16ed93fd51db702102fa5b06a41422
Parents: 4ce64a4
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 14:13:20 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
AlluraTest/alluratest/controller.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/506d4d01/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 6e3bb85..57d0fe4 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -190,8 +190,9 @@ class TestRestApiBase(TestController):
if username not in self._token_cache:
user = M.User.query.get(username=username)
consumer_token = M.OAuthConsumerToken(
- name='test',
- description='test-app')
+ name='test-%s' % str(user._id),
+ description='test-app-%s' % str(user._id),
+ user_id=user._id)
request_token = M.OAuthRequestToken(
consumer_token_id=consumer_token._id,
user_id=user._id,
[15/16] git commit: [#1687] ticket:582 Use OAuth instead of obsolete
ApiTicket auth in wiki-post script
Posted by br...@apache.org.
[#1687] ticket:582 Use OAuth instead of obsolete ApiTicket auth in wiki-post script
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/19a50da2
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/19a50da2
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/19a50da2
Branch: refs/heads/master
Commit: 19a50da24466f464191eb00a257df97eb9f8d497
Parents: c102aa9
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue May 6 15:13:25 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:23 2014 +0000
----------------------------------------------------------------------
scripts/wiki-post.py | 27 ++++++++-------------------
1 file changed, 8 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/19a50da2/scripts/wiki-post.py
----------------------------------------------------------------------
diff --git a/scripts/wiki-post.py b/scripts/wiki-post.py
index 038cf70..7e16bb1 100755
--- a/scripts/wiki-post.py
+++ b/scripts/wiki-post.py
@@ -19,9 +19,6 @@
import types
from sys import stdout
-import hmac
-import hashlib
-from datetime import datetime
import os
import urllib
from urllib2 import urlopen, HTTPError
@@ -76,18 +73,13 @@ def urlencode(params):
class Signer(object):
- def __init__(self, secret_key, api_key):
- self.secret_key = secret_key
- self.api_key = api_key
+ def __init__(self, token):
+ self.token = token
def __call__(self, path, params):
- if self.api_key is None:
+ if self.token is None:
return params
- params.append(('api_key', self.api_key))
- params.append(('api_timestamp', datetime.utcnow().isoformat()))
- message = path + '?' + urlencode(sorted(params))
- digest = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest()
- params.append(('api_signature', digest))
+ params.append(('token', self.token))
return params
@@ -95,8 +87,7 @@ def main():
usage = 'usage: %prog [options] [PageName [file]]'
op = OptionParser(usage=usage)
op.add_option('-c', '--config', metavar='CONFIG')
- op.add_option('-a', '--api-key', metavar='KEY')
- op.add_option('-s', '--secret-key', metavar='KEY')
+ op.add_option('-t', '--token', metavar='TOKEN')
op.add_option('', '--anon', action='store_true')
op.add_option('-u', '--url', metavar='URL')
(options, args) = op.parse_args()
@@ -119,18 +110,16 @@ def main():
config.read(
[str(os.path.expanduser('~/.forge-api.ini')), str(options.config)])
- api_key = None
- secret_key = None
+ token = None
if not options.anon:
- api_key = options.api_key or config.get('keys', 'api-key')
- secret_key = options.secret_key or config.get('keys', 'secret-key')
+ token = options.token or config.get('keys', 'token')
url = options.url or config.get('wiki', 'url')
if pagename_given:
url = urljoin(url, urllib.quote(pagename))
print url
- sign = Signer(secret_key, api_key)
+ sign = Signer(token)
params = [('text', markdown)] if method == 'PUT' else []
params = sign(urlparse(url).path, params)
try:
[06/16] git commit: [#1687] ticket:582 Add if_missing to
OAuthConsumerToken.description
Posted by br...@apache.org.
[#1687] ticket:582 Add if_missing to OAuthConsumerToken.description
Prevents /auth/oauth/ from raising errors about markdown_html being
absent (may happen when token created without description, e.g. in trac
importer)
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/c102aa90
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c102aa90
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c102aa90
Branch: refs/heads/master
Commit: c102aa909a3000d93cbfdb60b0dbbab617eeec1c
Parents: 66753dd
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue May 6 15:10:08 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
Allura/allura/model/oauth.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/c102aa90/Allura/allura/model/oauth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/oauth.py b/Allura/allura/model/oauth.py
index fd250bb..86dcb42 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -65,7 +65,7 @@ class OAuthConsumerToken(OAuthToken):
type = FieldProperty(str, if_missing='consumer')
user_id = AlluraUserProperty(if_missing=lambda: c.user._id)
name = FieldProperty(str)
- description = FieldProperty(str)
+ description = FieldProperty(str, if_missing='')
description_cache = FieldProperty(MarkdownCache)
user = RelationProperty('User')
[12/16] git commit: [#1687] ticket:589 Check if token allowed to
import forum
Posted by br...@apache.org.
[#1687] ticket:589 Check if token allowed to import forum
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/fd00be03
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/fd00be03
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/fd00be03
Branch: refs/heads/master
Commit: fd00be035d37c0b7e4218f1e33d7ddaccbc6baaf
Parents: 2392ea7
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed May 28 13:47:51 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:23 2014 +0000
----------------------------------------------------------------------
Allura/allura/model/oauth.py | 8 ++
.../forgediscussion/controllers/root.py | 5 +-
.../tests/functional/test_import.py | 134 ++++++++-----------
3 files changed, 65 insertions(+), 82 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/fd00be03/Allura/allura/model/oauth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/oauth.py b/Allura/allura/model/oauth.py
index 86dcb42..b09a8ec 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -21,6 +21,8 @@ import oauth2 as oauth
from pylons import tmpl_context as c, app_globals as g
import pymongo
+from paste.deploy.converters import aslist
+from tg import config
from ming import schema as S
from ming.orm import session
from ming.orm import FieldProperty, RelationProperty, ForeignIdProperty
@@ -134,3 +136,9 @@ class OAuthAccessToken(OAuthToken):
if user is None:
user = c.user
return cls.query.find(dict(user_id=user._id, type='access')).all()
+
+ def can_import_forum(self):
+ tokens = aslist(config.get('oauth.can_import_forum', ''), ',')
+ if self.api_key in tokens:
+ return True
+ return False
http://git-wip-us.apache.org/repos/asf/allura/blob/fd00be03/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index b315dca..9256662 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -349,9 +349,8 @@ class RootRestController(BaseController):
require_access(c.project, 'admin')
if username_mapping is None:
username_mapping = '{}'
- if c.api_token.get_capability('import') != [c.project.neighborhood.name, c.project.shortname]:
- log.error('Import capability is not enabled for %s',
- c.project.shortname)
+ if not c.api_token.can_import_forum():
+ log.error('Import capability is not enabled for %s', c.project.shortname)
raise exc.HTTPForbidden(detail='Import is not allowed')
try:
doc = json.loads(doc)
http://git-wip-us.apache.org/repos/asf/allura/blob/fd00be03/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index deeb349..73b0a8f 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -21,9 +21,11 @@ from datetime import datetime, timedelta
from nose.tools import assert_equal
import ming
+from tg import config
from pylons import tmpl_context as c
from allura import model as M
+from allura.lib import helpers as h
from alluratest.controller import TestRestApiBase
@@ -36,20 +38,15 @@ class TestImportController(TestRestApiBase): # TestController):
self.json_text = open(here_dir + '/data/sf.json').read()
def test_no_capability(self):
- self.set_api_ticket({'import2': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 403
+ with h.push_config(config, **{'oauth.can_import_forum': 'some,fake,tokens'}):
+ resp = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert resp.status_int == 403
- self.set_api_ticket({'import': ['Projects', 'test2']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 403
-
- self.set_api_ticket({'import': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert resp.status_int == 200
+ with h.push_config(config, **{'oauth.can_import_forum': self.token('test-admin').api_key}):
+ resp = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert resp.status_int == 200
def test_validate_import(self):
r = self.api_post('/rest/p/test/discussion/validate_import',
@@ -57,76 +54,55 @@ class TestImportController(TestRestApiBase): # TestController):
assert not r.json['errors']
def test_import_anon(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- r = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text)
- assert not r.json['errors'], r.json['errors']
- r = self.app.get('/p/test/discussion/')
- assert 'Open Discussion' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- for link in r.html.findAll('a'):
- if 'Welcome to Open Discussion' in str(link):
- break
- r = self.app.get(link.get('href'))
- assert '2009-11-19' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- assert 'Anonymous' in str(r)
+ with h.push_config(config, **{'oauth.can_import_forum': self.token('test-admin').api_key}):
+ r = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text)
+ assert not r.json['errors'], r.json['errors']
+ r = self.app.get('/p/test/discussion/')
+ assert 'Open Discussion' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ for link in r.html.findAll('a'):
+ if 'Welcome to Open Discussion' in str(link):
+ break
+ r = self.app.get(link.get('href'))
+ assert '2009-11-19' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ assert 'Anonymous' in str(r)
def test_import_map(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- r = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text,
- username_mapping=json.dumps(dict(rick446='test-user')))
- assert not r.json['errors'], r.json['errors']
- r = self.app.get('/p/test/discussion/')
- assert 'Open Discussion' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- for link in r.html.findAll('a'):
- if 'Welcome to Open Discussion' in str(link):
- break
- r = self.app.get(link.get('href'))
- assert '2009-11-19' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- assert 'Test User' in str(r)
- assert 'Anonymous' not in str(r)
+ with h.push_config(config, **{'oauth.can_import_forum': self.token('test-admin').api_key}):
+ r = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text,
+ username_mapping=json.dumps(dict(rick446='test-user')))
+ assert not r.json['errors'], r.json['errors']
+ r = self.app.get('/p/test/discussion/')
+ assert 'Open Discussion' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ for link in r.html.findAll('a'):
+ if 'Welcome to Open Discussion' in str(link):
+ break
+ r = self.app.get(link.get('href'))
+ assert '2009-11-19' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ assert 'Test User' in str(r)
+ assert 'Anonymous' not in str(r)
def test_import_create(self):
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- r = self.api_post('/rest/p/test/discussion/perform_import',
- doc=self.json_text, create_users='True')
- assert not r.json['errors'], r.json['errors']
- r = self.app.get('/p/test/discussion/')
- assert 'Open Discussion' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- for link in r.html.findAll('a'):
- if 'Welcome to Open Discussion' in str(link):
- break
- r = self.app.get(link.get('href'))
- assert '2009-11-19' in str(r)
- assert 'Welcome to Open Discussion' in str(r)
- assert 'Anonymous' not in str(r)
- assert 'test-rick446' in str(r)
-
- def set_api_ticket(self, caps={'import': ['Projects', 'test']}):
- api_ticket = M.ApiTicket(user_id=c.user._id, capabilities=caps,
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
+ with h.push_config(config, **{'oauth.can_import_forum': self.token('test-admin').api_key}):
+ r = self.api_post('/rest/p/test/discussion/perform_import',
+ doc=self.json_text, create_users='True')
+ assert not r.json['errors'], r.json['errors']
+ r = self.app.get('/p/test/discussion/')
+ assert 'Open Discussion' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ for link in r.html.findAll('a'):
+ if 'Welcome to Open Discussion' in str(link):
+ break
+ r = self.app.get(link.get('href'))
+ assert '2009-11-19' in str(r)
+ assert 'Welcome to Open Discussion' in str(r)
+ assert 'Anonymous' not in str(r)
+ assert 'test-rick446' in str(r)
@staticmethod
def time_normalize(t):
[04/16] git commit: [#1687] ticket:574 Remove ApiToken & ApiTicket
Posted by br...@apache.org.
[#1687] ticket:574 Remove ApiToken & ApiTicket
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/63652297
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/63652297
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/63652297
Branch: refs/heads/master
Commit: 6365229700600fc6e5720b4d90ab58bab39b2715
Parents: 65cc6e7
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 12:31:46 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:21 2014 +0000
----------------------------------------------------------------------
Allura/allura/controllers/rest.py | 18 ----
Allura/allura/controllers/site_admin.py | 49 ----------
Allura/allura/model/__init__.py | 2 +-
Allura/allura/model/auth.py | 99 --------------------
.../templates/site_admin_api_tickets.html | 66 -------------
5 files changed, 1 insertion(+), 233 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/63652297/Allura/allura/controllers/rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index abe6454..85a6df1 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -19,7 +19,6 @@
"""REST Controller"""
import logging
-from urllib import quote, unquote
import oauth2 as oauth
from webob import exc
@@ -50,23 +49,6 @@ class RestController(object):
'Based on request.params or oauth, authenticate the request'
if 'oauth_token' in request.params or 'access_token' in request.params:
return self.oauth._authenticate()
- elif 'api_key' in request.params:
- api_key = request.params.get('api_key')
- token = M.ApiTicket.get(api_key)
- if not token:
- token = M.ApiToken.get(api_key)
- else:
- log.info('Authenticating with API ticket')
- # Sometimes a path might be only partially escaped like /FAQ-Development,%20Bug%20Reporting,
- # I don't know why.
- path = quote(unquote(request.path))
- if path != request.path:
- log.info('Canonicalized %s to %s', request.path, path)
- if token is not None and token.authenticate_request(path, request.params):
- return token
- else:
- log.info('API authentication failure')
- raise exc.HTTPForbidden
else:
return None
http://git-wip-us.apache.org/repos/asf/allura/blob/63652297/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 352d35f..3cf4973 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -21,8 +21,6 @@ from datetime import datetime, timedelta
from tg import expose, validate, flash, config, redirect
from tg.decorators import with_trailing_slash, without_trailing_slash
-from ming.orm import session
-import pymongo
import bson
import tg
from pylons import app_globals as g
@@ -77,7 +75,6 @@ class SiteAdminController(object):
base_url = '/nf/admin/'
links = [
SitemapEntry('Home', base_url, ui_icon=g.icons['admin']),
- SitemapEntry('API Tickets', base_url + 'api_tickets', ui_icon=g.icons['admin']),
SitemapEntry('Add Subscribers', base_url + 'add_subscribers', ui_icon=g.icons['admin']),
SitemapEntry('New Projects', base_url + 'new_projects', ui_icon=g.icons['admin']),
SitemapEntry('Reclone Repo', base_url + 'reclone_repo', ui_icon=g.icons['admin']),
@@ -92,52 +89,6 @@ class SiteAdminController(object):
def index(self):
return {}
- @expose('jinja:allura:templates/site_admin_api_tickets.html')
- @without_trailing_slash
- def api_tickets(self, **data):
- import json
- import dateutil.parser
- if request.method == 'POST':
- log.info('api_tickets: %s', data)
- ok = True
- for_user = M.User.by_username(data['for_user'])
- if not for_user:
- ok = False
- flash('User not found')
- caps = None
- try:
- caps = json.loads(data['caps'])
- except ValueError:
- ok = False
- flash('JSON format error')
- if type(caps) is not type({}):
- ok = False
- flash(
- 'Capabilities must be a JSON dictionary, mapping capability name to optional discriminator(s) (or "")')
- try:
- expires = dateutil.parser.parse(data['expires'])
- except ValueError:
- ok = False
- flash('Date format error')
- if ok:
- tok = None
- try:
- tok = M.ApiTicket(user_id=for_user._id,
- capabilities=caps, expires=expires)
- session(tok).flush()
- log.info('New token: %s', tok)
- flash('API Ticket created')
- except:
- log.exception('Could not create API ticket:')
- flash('Error creating API ticket')
- elif request.method == 'GET':
- data = {'expires': datetime.utcnow() + timedelta(days=2)}
-
- data['token_list'] = M.ApiTicket.query.find().sort(
- 'mod_date', pymongo.DESCENDING).all()
- log.info(data['token_list'])
- return data
-
def subscribe_artifact(self, url, user):
artifact_url = urlparse(url).path[1:-1].split("/")
neighborhood = M.Neighborhood.query.find({
http://git-wip-us.apache.org/repos/asf/allura/blob/63652297/Allura/allura/model/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/__init__.py b/Allura/allura/model/__init__.py
index bc40872..a74bff6 100644
--- a/Allura/allura/model/__init__.py
+++ b/Allura/allura/model/__init__.py
@@ -25,7 +25,7 @@ from .index import ArtifactReference, Shortlink
from .artifact import Artifact, MovedArtifact, Message, VersionedArtifact, Snapshot, Feed, AwardFile, Award, AwardGrant, VotableArtifact
from .discuss import Discussion, Thread, PostHistory, Post, DiscussionAttachment
from .attachments import BaseAttachment
-from .auth import AuthGlobals, User, ProjectRole, EmailAddress, ApiToken, ApiTicket, OldProjectRole
+from .auth import AuthGlobals, User, ProjectRole, EmailAddress, OldProjectRole
from .auth import AuditLog, audit_log, AlluraUserProperty
from .filesystem import File
from .notification import Notification, Mailbox
http://git-wip-us.apache.org/repos/asf/allura/blob/63652297/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 7d56e8c..6a9d279 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -25,7 +25,6 @@ import hashlib
from urlparse import urlparse
from email import header
from hashlib import sha256
-import uuid
from pytz import timezone
from datetime import timedelta, datetime, time
@@ -110,104 +109,6 @@ class AlluraUserProperty(ForeignIdProperty):
super(AlluraUserProperty, self).__init__('User', allow_none=True, **kwargs)
-class ApiAuthMixIn(object):
-
- def authenticate_request(self, path, params):
- try:
- # Validate timestamp
- timestamp = iso8601.parse_date(params['api_timestamp'])
- timestamp_utc = timestamp.replace(
- tzinfo=None) - timestamp.utcoffset()
- if abs(datetime.utcnow() - timestamp_utc) > timedelta(minutes=10):
- return False
- # Validate signature
- api_signature = params['api_signature']
- params = sorted((k, v)
- for k, v in params.iteritems() if k != 'api_signature')
- string_to_sign = path + '?' + urlencode(params)
- digest = hmac.new(self.secret_key, string_to_sign, hashlib.sha256)
- return digest.hexdigest() == api_signature
- except KeyError:
- return False
-
- def sign_request(self, path, params):
- if hasattr(params, 'items'):
- params = params.items()
- has_api_key = has_api_timestamp = has_api_signature = False
- for k, v in params:
- if k == 'api_key':
- has_api_key = True
- if k == 'api_timestamp':
- has_api_timestamp = True
- if k == 'api_signature':
- has_api_signature = True
- if not has_api_key:
- params.append(('api_key', self.api_key))
- if not has_api_timestamp:
- params.append(('api_timestamp', datetime.utcnow().isoformat()))
- if not has_api_signature:
- string_to_sign = urllib.quote(path) + \
- '?' + urlencode(sorted(params))
- digest = hmac.new(self.secret_key, string_to_sign, hashlib.sha256)
- params.append(('api_signature', digest.hexdigest()))
- return params
-
- def get_capability(self, key):
- return None
-
-
-class ApiToken(MappedClass, ApiAuthMixIn):
-
- class __mongometa__:
- name = 'api_token'
- session = main_orm_session
- unique_indexes = ['user_id']
-
- _id = FieldProperty(S.ObjectId)
- user_id = AlluraUserProperty()
- api_key = FieldProperty(str, if_missing=lambda: str(uuid.uuid4()))
- secret_key = FieldProperty(str, if_missing=h.cryptographic_nonce)
-
- user = RelationProperty('User')
-
- @classmethod
- def get(cls, api_key):
- return cls.query.get(api_key=api_key)
-
-
-class ApiTicket(MappedClass, ApiAuthMixIn):
-
- class __mongometa__:
- name = 'api_ticket'
- session = main_orm_session
- PREFIX = 'tck'
-
- _id = FieldProperty(S.ObjectId)
- user_id = AlluraUserProperty()
- api_key = FieldProperty(
- str, if_missing=lambda: ApiTicket.PREFIX + h.nonce(20))
- secret_key = FieldProperty(str, if_missing=h.cryptographic_nonce)
- expires = FieldProperty(datetime, if_missing=None)
- capabilities = FieldProperty({str: None})
- mod_date = FieldProperty(datetime, if_missing=datetime.utcnow)
-
- user = RelationProperty('User')
-
- @classmethod
- def get(cls, api_ticket):
- if not api_ticket.startswith(cls.PREFIX):
- return None
- return cls.query.get(api_key=api_ticket)
-
- def authenticate_request(self, path, params):
- if self.expires and datetime.utcnow() > self.expires:
- return False
- return ApiAuthMixIn.authenticate_request(self, path, params)
-
- def get_capability(self, key):
- return self.capabilities.get(key)
-
-
class EmailAddress(MappedClass):
re_format = re.compile('^.* <(.*)>$')
http://git-wip-us.apache.org/repos/asf/allura/blob/63652297/Allura/allura/templates/site_admin_api_tickets.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin_api_tickets.html b/Allura/allura/templates/site_admin_api_tickets.html
deleted file mode 100644
index 0dba2ea..0000000
--- a/Allura/allura/templates/site_admin_api_tickets.html
+++ /dev/null
@@ -1,66 +0,0 @@
-{#-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--#}
-{% set page="api_tickets" %}
-{% extends 'allura:templates/site_admin.html' %}
-
-{% block content %}
-<h1>Special API Tickets</h1>
-<p>API Tickets give access to special APIs which should be used under supervision.
-</p>
-
-<form name="ticket_form" method="POST">
-<table>
-<tr>
-<td>Username:</td> <td><input name="for_user" type="text" value="{{for_user}}"></td>
-</tr>
-<tr>
-<td>Capabilities (JSON):</td> <td><input name="caps" type="text" value="{{caps}}"></td>
-</tr>
-<tr>
-<td>Expiration date:</td> <td><input name="expires" type="text" value="{{expires}}"></td>
-</tr>
-<tr>
-<td><input type="submit" value="Save"><td>
-</tr>
-</table>
-{{lib.csrf_token()}}
-</form>
-
-<table>
-<tr>
-<th>Username</th>
-<th>Expiration Date</th>
-<th>Capabilities</th>
-</tr>
-{% for token in token_list %}
-<tr>
-<td>{{token.user.username}}</td>
-<td>{{token.expires}}</td>
-<td>{{h.json.dumps(token.capabilities)}}</td>
-<td></td>
-</tr>
-<tr>
-<td colspan="3">
- API Ticket: {{token.api_key}}<br/>
- Secret Key: {{token.secret_key}}</td>
-</tr>
-{% endfor %}
-</table>
-
-{% endblock %}
[08/16] git commit: [#1687] ticket:574 Remove old tracker import and
related tests
Posted by br...@apache.org.
[#1687] ticket:574 Remove old tracker import and related tests
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7b65cf2a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7b65cf2a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7b65cf2a
Branch: refs/heads/master
Commit: 7b65cf2a29216dbf76adcabe52bc10dfa7f9140e
Parents: 506d4d0
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 17:10:37 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:22 2014 +0000
----------------------------------------------------------------------
.../tests/functional/test_import.py | 210 -------------------
ForgeTracker/forgetracker/tracker_main.py | 28 ---
2 files changed, 238 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/7b65cf2a/ForgeTracker/forgetracker/tests/functional/test_import.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_import.py b/ForgeTracker/forgetracker/tests/functional/test_import.py
deleted file mode 100644
index 9d47543..0000000
--- a/ForgeTracker/forgetracker/tests/functional/test_import.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# -*- coding: utf-8 -*-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import os
-import json
-from formencode.variabledecode import variable_encode
-from datetime import datetime, timedelta
-from nose.tools import assert_equal, assert_false
-
-import ming
-from pylons import app_globals as g
-from pylons import tmpl_context as c
-
-from allura import model as M
-from allura.lib import helpers as h
-from alluratest.controller import TestRestApiBase
-from allura.tests import decorators as td
-
-
-class TestImportController(TestRestApiBase):
-
- def new_ticket(self, mount_point='/bugs/', **kw):
- response = self.app.get(mount_point + 'new/')
- form = response.forms[1]
- for k, v in kw.iteritems():
- form['ticket_form.%s' % k] = v
- resp = form.submit()
- if resp.status_int == 200:
- resp.showbrowser()
- assert 0, "form error?"
- return resp.follow()
-
- def set_api_ticket(self, caps={'import': ['Projects', 'test']}):
- api_ticket = M.ApiTicket(user_id=c.user._id, capabilities=caps,
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- @td.with_tracker
- def test_no_capability(self):
- here_dir = os.path.dirname(__file__)
-
- self.set_api_ticket({'import2': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/bugs/perform_import',
- doc=open(here_dir + '/data/sf.json').read(), options='{}')
- assert resp.status_int == 403
-
- self.set_api_ticket({'import': ['Projects', 'test2']})
- resp = self.api_post('/rest/p/test/bugs/perform_import',
- doc=open(here_dir + '/data/sf.json').read(), options='{}')
- assert resp.status_int == 403
-
- self.set_api_ticket({'import': ['Projects', 'test']})
- resp = self.api_post('/rest/p/test/bugs/perform_import',
- doc=open(here_dir + '/data/sf.json').read(), options='{}')
- assert resp.status_int == 200
-
- @staticmethod
- def time_normalize(t):
- return t.replace('T', ' ').replace('Z', '')
-
- def verify_ticket(self, from_api, org):
- assert_equal(from_api['status'], org['status'])
- assert_equal(from_api['description'], org['description'])
- assert_equal(from_api['summary'], org['summary'])
- assert_equal(from_api['ticket_num'], org['id'])
- assert_equal(from_api['created_date'],
- self.time_normalize(org['date']))
- assert_equal(from_api['mod_date'],
- self.time_normalize(org['date_updated']))
- assert_equal(from_api['custom_fields']
- ['_resolution'], org['resolution'])
- assert_false('_cc' in from_api['custom_fields'])
- assert_equal(from_api['custom_fields']['_private'], org['private'])
-
- @td.with_tracker
- def test_validate_import(self):
- here_dir = os.path.dirname(__file__)
- doc_text = open(here_dir + '/data/sf.json').read()
- r = self.api_post('/rest/p/test/bugs/validate_import',
- doc=doc_text, options='{}')
- assert not r.json['errors']
-
- @td.with_tracker
- def test_import_custom_field(self):
- params = dict(
- custom_fields=[
- dict(name='_resolution', label='Resolution', type='select',
- options='oné "one and á half" two'),
- ],
- open_status_names='aa bb',
- closed_status_names='cc',
- )
- self.app.post(
- '/admin/bugs/set_custom_fields',
- params=variable_encode(params))
- here_dir = os.path.dirname(__file__)
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- doc_text = open(here_dir + '/data/sf.json').read()
- doc_json = json.loads(doc_text)
- ticket_json = doc_json['trackers']['default']['artifacts'][0]
- r = self.api_post('/rest/p/test/bugs/perform_import',
- doc=doc_text, options='{"user_map": {"hinojosa4": "test-admin", "ma_boehm": "test-user"}}')
- assert r.json['status'], r.json
-
- ming.orm.ThreadLocalORMSession.flush_all()
- M.MonQTask.run_ready()
- ming.orm.ThreadLocalORMSession.flush_all()
-
- r = self.app.get('/p/test/bugs/204/')
- assert '<option selected value="fixed">fixed</option>' in r
- assert '<option value="one and á half">one and á half</option>' in r
-
- @td.with_tracker
- def test_import(self):
- here_dir = os.path.dirname(__file__)
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- doc_text = open(here_dir + '/data/sf.json').read()
- doc_json = json.loads(doc_text)
- ticket_json = doc_json['trackers']['default']['artifacts'][0]
- r = self.api_post('/rest/p/test/bugs/perform_import',
- doc=doc_text, options='{"user_map": {"hinojosa4": "test-admin", "ma_boehm": "test-user"}}')
- assert r.json['status']
- assert r.json['errors'] == []
-
- ming.orm.ThreadLocalORMSession.flush_all()
- M.MonQTask.run_ready()
- ming.orm.ThreadLocalORMSession.flush_all()
-
- indexed_tickets = filter(
- lambda a: a['type_s'] == 'Ticket', g.solr.db.values())
- assert_equal(len(indexed_tickets), 1)
- assert_equal(indexed_tickets[0]['summary_t'], ticket_json['summary'])
- assert_equal(indexed_tickets[0]['ticket_num_i'], ticket_json['id'])
-
- r = self.app.get('/rest/p/test/bugs/204/')
- self.verify_ticket(r.json['ticket'], ticket_json)
- assert r.json['ticket']["reported_by"] == "test-user"
- assert r.json['ticket']["assigned_to"] == "test-admin"
-
- r = self.app.get('/rest/p/test/bugs/')
- assert len(r.json['tickets']) == 1
- assert_equal(r.json['tickets'][0]['ticket_num'], ticket_json['id'])
- assert_equal(r.json['tickets'][0]['summary'], ticket_json['summary'])
-
- r = self.app.get('/p/test/bugs/204/')
- assert '<option value="2.0">2.0</option>' in r
- assert '<option selected value="test_milestone">test_milestone</option>' in r
- assert ticket_json['summary'] in r
- r = self.app.get('/p/test/bugs/')
- assert ticket_json['summary'] in r
-
- @td.with_tracker
- def test_milestone_status(self):
- """When importing, if all tickets in a milestone are closed, the
- milestone itself should also be closed.
-
- """
- here_dir = os.path.dirname(__file__)
- api_ticket = M.ApiTicket(
- user_id=c.user._id, capabilities={'import': ['Projects', 'test']},
- expires=datetime.utcnow() + timedelta(days=1))
- ming.orm.session(api_ticket).flush()
- self.set_api_token(api_ticket)
-
- doc_text = open(here_dir + '/data/milestone-tickets.json').read()
- r = self.api_post('/rest/p/test/bugs/perform_import', doc=doc_text,
- options='{"user_map": {"hinojosa4": "test-admin", "ma_boehm": "test-user"}}')
- assert r.json['status'], r.json
-
- ming.orm.ThreadLocalORMSession.flush_all()
- M.MonQTask.run_ready()
- ming.orm.ThreadLocalORMSession.flush_all()
-
- with h.push_context('test', mount_point='bugs', neighborhood='Projects'):
- for milestone_fld in c.app.globals.milestone_fields:
- milestone_names = [ms['name']
- for ms in milestone_fld['milestones']]
- assert 'open_milestone' in milestone_names, milestone_names
- assert 'closed_milestone' in milestone_names, milestone_names
- for milestone in milestone_fld['milestones']:
- if milestone['name'] == 'open_milestone':
- assert milestone['complete'] == False
- if milestone['name'] == 'closed_milestone':
- assert milestone['complete'] == True
http://git-wip-us.apache.org/repos/asf/allura/blob/7b65cf2a/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 542f512..d37b5b1 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1716,34 +1716,6 @@ class RootRestController(BaseController):
redirect(str(ticket.ticket_num) + '/')
@expose('json:')
- def validate_import(self, doc=None, options=None, **post_data):
- require_access(c.project, 'admin')
- migrator = ImportSupport()
- try:
- status = migrator.validate_import(doc, options, **post_data)
- return status
- except Exception, e:
- log.exception(e)
- return dict(status=False, errors=[repr(e)])
-
- @expose('json:')
- def perform_import(self, doc=None, options=None, **post_data):
- with h.notifications_disabled(c.project):
- require_access(c.project, 'admin')
- if c.api_token.get_capability('import') != [c.project.neighborhood.name, c.project.shortname]:
- log.error('Import capability is not enabled for %s',
- c.project.shortname)
- raise exc.HTTPForbidden(detail='Import is not allowed')
-
- migrator = ImportSupport()
- try:
- status = migrator.perform_import(doc, options, **post_data)
- return status
- except Exception, e:
- log.exception(e)
- return dict(status=False, errors=[str(e)])
-
- @expose('json:')
def search(self, q=None, limit=100, page=0, sort=None, **kw):
results = TM.Ticket.paged_search(
c.app.config, c.user, q, limit, page, sort, show_deleted=False)
[03/16] git commit: [#1687] ticket:574 Change TestRestApiBase to use
oauth
Posted by br...@apache.org.
[#1687] ticket:574 Change TestRestApiBase to use oauth
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/44a7f5ec
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/44a7f5ec
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/44a7f5ec
Branch: refs/heads/master
Commit: 44a7f5ec2e474c4b59bda024798c98c7c8b4c465
Parents: 6365229
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri May 2 13:06:15 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jun 3 15:27:21 2014 +0000
----------------------------------------------------------------------
AlluraTest/alluratest/controller.py | 41 +++++++++++++++++---------------
1 file changed, 22 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/44a7f5ec/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index a7131ef..6e3bb85 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -189,15 +189,28 @@ class TestRestApiBase(TestController):
# only create token once, else ming gets dupe key error
if username not in self._token_cache:
user = M.User.query.get(username=username)
- token = M.ApiToken(user_id=user._id)
+ consumer_token = M.OAuthConsumerToken(
+ name='test',
+ description='test-app')
+ request_token = M.OAuthRequestToken(
+ consumer_token_id=consumer_token._id,
+ user_id=user._id,
+ callback='manual',
+ validation_pin=h.nonce(20),
+ is_bearer=True)
+ token = M.OAuthAccessToken(
+ consumer_token_id=consumer_token._id,
+ request_token_id=request_token._id,
+ user_id=user._id,
+ is_bearer=True)
+ ming.orm.session(consumer_token).flush()
+ ming.orm.session(request_token).flush()
ming.orm.session(token).flush()
self._token_cache[username] = token
return self._token_cache[username]
- def _api_getpost(
- self, method, path, api_key=None, api_timestamp=None, api_signature=None,
- wrap_args=None, user='test-admin', status=None, **params):
+ def _api_getpost(self, method, path, wrap_args=None, user='test-admin', status=None, **params):
'''
If you need to use one of the method kwargs as a URL parameter,
pass params={...} as a dict instead of **kwargs
@@ -209,14 +222,8 @@ class TestRestApiBase(TestController):
if status is None:
status = [200, 201, 301, 302, 400, 403, 404]
params = variabledecode.variable_encode(params, add_repetitions=False)
- if api_key:
- params['api_key'] = api_key
- if api_timestamp:
- params['api_timestamp'] = api_timestamp
- if api_signature:
- params['api_signature'] = api_signature
- params = self.token(user).sign_request(path, params)
+ params['access_token'] = self.token(user).api_key
fn = self.app.post if method == 'POST' else self.app.get
@@ -229,12 +236,8 @@ class TestRestApiBase(TestController):
else:
return response
- def api_get(
- self, path, api_key=None, api_timestamp=None, api_signature=None,
- wrap_args=None, user='test-admin', status=None, **params):
- return self._api_getpost('GET', path, api_key, api_timestamp, api_signature, wrap_args, user, status, **params)
+ def api_get(self, path, wrap_args=None, user='test-admin', status=None, **params):
+ return self._api_getpost('GET', path, wrap_args, user, status, **params)
- def api_post(
- self, path, api_key=None, api_timestamp=None, api_signature=None,
- wrap_args=None, user='test-admin', status=None, **params):
- return self._api_getpost('POST', path, api_key, api_timestamp, api_signature, wrap_args, user, status, **params)
+ def api_post(self, path, wrap_args=None, user='test-admin', status=None, **params):
+ return self._api_getpost('POST', path, wrap_args, user, status, **params)