def query_users(self, query, request): if not query: return try: bugzilla = Bugzilla(get_bugzilla_api_key(request.user)) except BugzillaError as e: raise UserQueryError('Bugzilla error: %s' % e.msg) try: # We don't want to auto populate just any user because Bugzilla has # over 300,000 users and most of them aren't relevant to MozReview. # # So, we only auto import users if they have IRC nick syntax or # if the search matches them exactly. def user_relevant(u): if BZ_IRCNICK_RE.search(u['real_name']): return True if u['email'] == query: return True # This might allow too many users through. Let's not get too # attached to this. if u['real_name'] == query: return True return False users = bugzilla.query_users(query) users['users'] = [u for u in users['users'] if user_relevant(u)] get_or_create_bugzilla_users(users) except BugzillaError as e: raise UserQueryError('Bugzilla error: %s' % e.msg)
def get_or_create_user(self, username, request): """Always check Bugzilla for updates.""" username = username.strip() try: bugzilla = Bugzilla(get_bugzilla_api_key(request.user)) except BugzillaUrlError: return None except BugzillaError: raise PermissionDenied user_data = bugzilla.get_user(username) if not user_data: raise self.bz_error_response(request) # Just store the results. get_or_create_bugzilla_users(user_data) try: return User.objects.get(username=username) except User.DoesNotExist: return None
def query_users(self, query, request): if not query: return try: bugzilla = Bugzilla(get_bugzilla_api_key(request.user)) except BugzillaError as e: raise UserQueryError('Bugzilla error: %s' % e.msg) try: # We don't want to auto populate just any user because Bugzilla has # over 300,000 users and most of them aren't relevant to MozReview. # # So, we only auto import users if they have IRC nick syntax or # if the search matches them exactly. def user_relevant(u): if BMO_IRC_NICK_RE.search(u['real_name']): return True if u['email'] == query: return True # This might allow too many users through. Let's not get too # attached to this. if u['real_name'] == query: return True return False users = bugzilla.query_users(query) users['users'] = [u for u in users['users'] if user_relevant(u)] logger.info( 'importing Bugzilla users from query "%s": %s' % (query, ', '.join(sorted(u['email'] for u in users['users'])))) get_or_create_bugzilla_users(users) except BugzillaError as e: raise UserQueryError('Bugzilla error: %s' % e.msg)
def authenticate_api_key(self, username, api_key): """Authenticate a user from a username and API key. This is intended to be used by the Web API and not a user-facing login form. We enforce that the user already exists and has an API key - not necessarily the same API key - on file. The API key passed in is only used for authentication: all subsequent communication with Bugzilla should be performed using the API key on file. We require the user already exist in the database because having the user go through the browser-facing login flow is the most sane (and secure) way to obtain an API key. We don't want to store the API key provided to us from the client because API keys obtained by the browser login may have special permissions not granted to normal API keys. """ username = username.strip() try: bugzilla = Bugzilla() except BugzillaUrlError: logging.warn('Login failure for user %s: Bugzilla URL not set.' % username) try: valid = bugzilla.valid_api_key(username, api_key) except BugzillaError as e: logging.error('Login failure for user %s: %s' % (username, e)) return None if not valid: logging.error('Login failure for user %s: invalid API key' % username) assert bugzilla.base_url.endswith('/') raise BugzillaAPIKeyNeededError( bugzilla.base_url + 'userprefs.cgi?tab=apikey') # Assign the API key to the Bugzilla connection so the user info # lookup uses it. # TODO can we skip valid_api_key() and just get user info straight up? bugzilla.api_key = api_key try: user_data = bugzilla.get_user(username) except BugzillaError as e: logging.error('Login failure for user %s: unable to retrieve ' 'Bugzilla user info: %s' % (username, e)) return None if not user_data: logging.warning('Could not retrieve user info for %s after ' 'validating API key' % username) return None bz_user = user_data['users'][0] try: bum = BugzillaUserMap.objects.get(bugzilla_user_id=bz_user['id']) user = bum.user except BugzillaUserMap.DoesNotExist: logging.warning('Login failure for user %s: API key valid but ' 'user missing from database' % username) raise WebLoginNeededError() if not user.is_active: logging.error('Login failure for user %s: user not active' % username) return None # We require a local API key to be on file, as it will be used for # subsequent requests. if not get_bugzilla_api_key(user): logging.warning('Login failure for user %s: no API key in ' 'database' % username) raise WebLoginNeededError() return user
def authenticate_api_key(self, username, api_key): """Authenticate a user from a username and API key. This is intended to be used by the Web API and not a user-facing login form. We enforce that the user already exists and has an API key - not necessarily the same API key - on file. The API key passed in is only used for authentication: all subsequent communication with Bugzilla should be performed using the API key on file. We require the user already exist in the database because having the user go through the browser-facing login flow is the most sane (and secure) way to obtain an API key. We don't want to store the API key provided to us from the client because API keys obtained by the browser login may have special permissions not granted to normal API keys. """ username = username.strip() logger.info('Login attempt (apikey) for user %s: ' % username) try: bugzilla = Bugzilla() except BugzillaUrlError: logger.warn('Login failure (apikey) for user %s: Bugzilla URL ' 'not set.' % username) try: valid = bugzilla.valid_api_key(username, api_key) except BugzillaError as e: logger.error('Login failure (apikey) for user %s: %s' % (username, e)) return None if not valid: logger.error('Login failure for user %s: invalid API key' % username) assert bugzilla.base_url.endswith('/') raise BugzillaAPIKeyNeededError(bugzilla.base_url + 'userprefs.cgi?tab=apikey') # Assign the API key to the Bugzilla connection so the user info # lookup uses it. # TODO can we skip valid_api_key() and just get user info straight up? bugzilla.api_key = api_key try: user_data = bugzilla.get_user(username) except BugzillaError as e: logger.error('Login failure (apikey) for user %s: unable to ' 'retrieve Bugzilla user info: %s' % (username, e)) return None if not user_data: logger.warning('Could not retrieve user info for %s after ' 'validating API key' % username) return None bz_user = user_data['users'][0] try: bum = BugzillaUserMap.objects.get(bugzilla_user_id=bz_user['id']) user = bum.user except BugzillaUserMap.DoesNotExist: logger.warning('Login failure for user %s: API key valid but ' 'user missing from database' % username) raise WebLoginNeededError() if not user.is_active: logger.error('Login failure (apikey) for user %s: user not ' 'active' % username) return None # We require a local API key to be on file, as it will be used for # subsequent requests. if not get_bugzilla_api_key(user): logger.warning('Login failure for user %s: no API key in ' 'database' % username) raise WebLoginNeededError() logger.info('Login successful (apikey) for user %s: ' % username) return user