[#6612] Allow direct user-mapping for SF Trac imports
Signed-off-by: Tim Van Steenburgh <tvansteenburgh@gmail.com>
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 770ae72..298b09e 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -78,8 +78,10 @@
expires=now + timedelta(minutes=60))
api_client = ApiClient.return_value
import_tracker.assert_called_once_with(
- api_client, 'myproject', 'bugs',
- {"user_map": user_map}, '[]',
+ api_client, 'myproject', 'bugs', {
+ "user_map": user_map,
+ "usernames_match": False,
+ }, '[]',
validate=False)
AuditLog.log.assert_called_once_with(
'import tool bugs from http://example.com/trac/url/',
@@ -108,11 +110,12 @@
class TestTracTicketImportController(TestController, TestCase):
- def setUp(self):
+ @patch('forgeimporters.trac.tickets.import_tool')
+ def setUp(self, import_tool):
"""Mount Trac import controller on the Tracker admin controller"""
super(TestTracTicketImportController, self).setUp()
from forgetracker.tracker_main import TrackerAdminController
- TrackerAdminController._importer = TracTicketImportController()
+ self.importer = TrackerAdminController._importer = TracTicketImportController()
@with_tracker
def test_index(self):
@@ -122,8 +125,8 @@
self.assertIsNotNone(r.html.find(attrs=dict(name="mount_point")))
@with_tracker
- @patch('forgeimporters.trac.tickets.import_tool')
- def test_create(self, import_tool):
+ def test_create(self):
+ import_tool = self.importer.task
params = dict(trac_url='http://example.com/trac/url',
mount_label='mylabel',
mount_point='mymount',
@@ -138,8 +141,8 @@
self.assertEqual(u'http://example.com/trac/url', import_tool.post.call_args[1]['trac_url'])
@with_tracker
- @patch('forgeimporters.trac.tickets.import_tool')
- def test_create_limit(self, import_tool):
+ def test_create_limit(self):
+ import_tool = self.importer.task
project = M.Project.query.get(shortname='test')
project.set_tool_data('TracTicketImporter', pending=1)
ThreadLocalORMSession.flush_all()
diff --git a/ForgeImporters/forgeimporters/trac/tickets.py b/ForgeImporters/forgeimporters/trac/tickets.py
index 9b222b9..6b2600a 100644
--- a/ForgeImporters/forgeimporters/trac/tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tickets.py
@@ -73,6 +73,7 @@
class TracTicketImportController(BaseController):
def __init__(self):
self.importer = TracTicketImporter()
+ self.task = import_tool
@property
def target_app(self):
@@ -89,8 +90,8 @@
@require_post()
@validate(TracTicketImportForm(ForgeTrackerApp), error_handler=index)
def create(self, trac_url, mount_point, mount_label, user_map=None, **kw):
- if TracTicketImporter().enforce_limit(c.project):
- import_tool.post(
+ if self.importer.enforce_limit(c.project):
+ self.task.post(
mount_point=mount_point,
mount_label=mount_label,
trac_url=trac_url,
@@ -138,8 +139,10 @@
session(api_ticket).flush(api_ticket)
cli = AlluraImportApiClient(config['base_url'], api_ticket.api_key,
api_ticket.secret_key, verbose=True, retry=False)
- import_tracker(cli, project.shortname, mount_point,
- {'user_map': json.loads(user_map) if user_map else {}},
+ import_tracker(cli, project.shortname, mount_point, {
+ 'user_map': json.loads(user_map) if user_map else {},
+ 'usernames_match': self.usernames_match(trac_url),
+ },
export_string, validate=False)
AuditLog.log(
'import tool %s from %s' % (
@@ -150,6 +153,20 @@
)
g.post_event('project_updated')
return app
- except Exception as e:
+ except Exception:
h.make_app_admin_only(app)
raise
+
+ def usernames_match(self, trac_url):
+ """Return True if the usernames in the source Trac match the usernames
+ in the destination Allura instance.
+
+ If this is True, Trac usernames will be mapped to their Allura
+ counterparts regardless of whether a user_map file is supplied.
+
+ If this is False, any Trac username not present in the user_map file
+ (or if no file is supplied) will be assumed an unknown or non-existent
+ user in the Allura instance.
+
+ """
+ return False
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index 36c686e..c6a33cb 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -107,7 +107,7 @@
self.FIELD_MAP = {
'assigned_to': ('assigned_to_id', self.get_user_id),
'class': None,
- 'date': ('created_date', self.parse_date),
+ 'date': ('created_date', self.parse_date),
'date_updated': ('mod_date', self.parse_date),
'description': True,
'id': None,
@@ -142,11 +142,18 @@
return datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%SZ')
def get_user_id(self, username):
- username = self.options['user_map'].get(username)
- if not username:
- return None
- u = M.User.by_username(username)
- return u._id if u else None
+ def _get_user_id(username):
+ u = M.User.by_username(username)
+ return u._id if u else None
+
+ if self.options.get('usernames_match'):
+ return _get_user_id(username)
+
+ mapped_username = self.options['user_map'].get(username)
+ if mapped_username:
+ return _get_user_id(mapped_username)
+
+ return None
def check_custom_field(self, field, value, ticket_status):
field = c.app.globals.get_custom_field(field)
@@ -347,7 +354,7 @@
unknown_users = self.find_unknown_users(users)
unknown_users = sorted(list(unknown_users))
if unknown_users:
- self.warnings.append('''Document references unknown users. You should provide
+ self.warnings.append('''Document references unknown users. You should provide
option user_map to avoid losing username information. Unknown users: %s''' % unknown_users)
return {'status': True, 'errors': self.errors, 'warnings': self.warnings}