def _users_query(self, q, limit=10): from simplifiedpermissionsadminplugin.simplifiedpermissions import SimplifiedPermissions if SimplifiedPermissions and self.env.is_enabled(SimplifiedPermissions): sp = SimplifiedPermissions(self.env) # Keep track of users that have already been found to prevent # yielding duplicates of users belonging to several groups yielded_sids = set() for group, data in sp.group_memberships().items(): for member in data['members']: if q in member.sid and member.sid not in yielded_sids: # if the 'never logged in' text changes, then update # plugins/open/autocompleteplugin/autocompleteplugin/htdocs/js/jquery.tracautocomplete.js yield {'sid': member.sid, 'name': member.get('name', member.sid), 'email': member.get('email','')} yielded_sids.add(member.sid) else: perm = PermissionSystem(self.env) users = [sid for sid, permission in perm.get_all_permissions() if sid not in set("anonymous", "authenticated", "admin")] for sid in sorted(set(users)): if q in sid: session = DetachedSession(self.env, sid) yield {'sid': sid, 'name': session.get('name',''), 'email': session.get('email','Never logged in')}
def _get_address_info(self, authname): "TODO: check env.get_known_users" # First check if it's a #define user sess = DetachedSession(self.env, authname) address = sess.get('email') real_name = None if not address: # Otherwise check if it's a valid email address real_name, address = self.parse_address(authname) if not address: if not sess.get('email'): raise ValueError(_('User %(user)s has no email address set', user=authname)) else: raise ValueError(_('%(address)s is not a valid email address', address=address)) if not real_name: real_name = sess.get('name') return real_name, address
def _get_ticket_data(self, req, results): ats = AgileToolsSystem(self.env) loc = LogicaOrderController(self.env) closed_statuses = loc.type_and_statuses_for_closed_statusgroups() # TODO calculate which statuses are closed using the query system # when it is able to handle this tickets = [] for result in results: if result['status'] not in closed_statuses[result['type']]: filtered_result = dict((k, v) for k, v in result.iteritems() if k in self.fields) if "remaininghours" in filtered_result: try: hours = float(filtered_result["remaininghours"]) except (ValueError, TypeError): hours = 0 del filtered_result["remaininghours"] else: hours = 0 if "effort" in filtered_result: try: storypoints = float(filtered_result['effort']) except (ValueError, TypeError): storypoints = 0 else: storypoints = 0 reporter = filtered_result["reporter"] session = DetachedSession(self.env, reporter) filtered_result.update({ 'id': result['id'], 'position': ats.position(result['id']), 'hours': hours, 'effort': storypoints, 'reporter': session.get('name', reporter), 'changetime': to_utimestamp(filtered_result['changetime']) }) tickets.append(filtered_result) return tickets
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, oidsession = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args, req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' session_attr = {} # attributes for new "user" # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url), ) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri, []) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = (' '.join( filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or (email and email.split('@', 1)[0].replace('.', ' ').title())) nickname = sreg_info.get('nickname') if self.groups_to_request and TeamsResponse: teams_response = TeamsResponse.fromSuccessResponse(info) if teams_response: # be careful not to make user a member of any trac groups # not named in groups_to_request teams = set(teams_response.teams).intersection( self.groups_to_request) if teams: session_attr['openid.teams'] = ','.join(teams) if self.strip_protocol: remote_user = remote_user[remote_user.find('://') + 3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += ( " This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID), )) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug( "Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug( "Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and self.re_email_white_list: self.env.log.debug( "Filtering email %r through email white-list." % email) allowed = False if email: for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: allowed = False params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) try: result = json.load(urllib.urlopen(url)) if result[self.check_list_key]: if self.check_list_username: cl_username = unicode( result[self.check_list_username]) if not cl_username: raise ValueError("Bad value for username") allowed = True except Exception, ex: self.env.log.error('OpenID check_list failed: %s' % ex) if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime session_attr[ self.openid_session_identity_url_key] = info.identity_url if email: session_attr['email'] = email if fullname: session_attr['name'] = fullname self._commit_oidsession(oidsession, req) if self.check_list and self.check_list_username: authname = cl_username elif self.use_nickname_as_authname and nickname: authname = nickname elif session_attr.get('name'): authname = session_attr['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) else: authname = remote_user # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() if self.trust_authname: ds = DetachedSession(self.env, authname) else: # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # session with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) existing_users_and_groups = set( user for user, perm in PermissionSystem( self.env).get_all_permissions()) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. if authname in existing_users_and_groups: # Permissions are already defined for this user continue break ds_identity = ds.get( self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break if ds and (ds.last_visit != 0 or len(ds) > 0): # The user already exists, update team membership # XXX: Should also update name and/or email? (This would # be an API change.) for name in ['openid.teams']: if name in session_attr: ds[name] = session_attr[name] elif name in ds: del ds[name] ds.save() else: # We are creating a new "user". Set attributes on the # current anonymous session. It will be promoted to # the new authenticated session on the next request # (by Session.__init__). # # NB: avoid dict.update here to ensure that # DetachedSession.__getitem__ gets a chance to # normalize values for name, value in session_attr.items(): req.session[name] = value req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address( req.remote_addr), int(time.time()))) db.commit() req.redirect( req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.'
def get_permission_groups(self, username): ds = DetachedSession(self.env, username) return ds.get('openid.teams', '').split(',')
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, session = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args,req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri,[]) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = (' '.join(filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or email.split('@',1)[0].replace('.', ' ').title()) if self.strip_protocol: remote_user = remote_user[remote_user.find('://')+3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and email and self.re_email_white_list: self.env.log.debug("Filtering email '%s' through email white-list." % email) allowed = False for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) result = json.load(urllib.urlopen(url)) if not result[self.check_list_key]: allowed = False elif self.check_list_username: new_user = result[self.check_list_username] if new_user: remote_user = new_user if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime req.session[self.openid_session_identity_url_key] = info.identity_url if email: req.session['email'] = email if fullname: req.session['name'] = fullname self._commit_session(session, req) if req.session.get('name'): authname = req.session['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # ssession with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. break ds_identity = ds.get(self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.redirect(req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.' elif info.status == consumer.CANCEL: # cancelled message = 'Verification cancelled' elif info.status == consumer.SETUP_NEEDED: if info.setup_url: message = '<a href=%s>Setup needed</a>' % ( quoteattr(info.setup_url),) else: # This means auth didn't succeed, but you're welcome to try # non-immediate mode. message = 'Setup needed' else: # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. message = 'Verification failed.' self._commit_session(session, req) add_stylesheet(req, 'authopenid/css/openid.css') add_script(req, 'authopenid/js/openid-jquery.js') return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': message, 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': css_class, 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, oidsession = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args,req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' session_attr = {} # attributes for new "user" # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri,[]) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = ( ' '.join(filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or (email and email.split('@',1)[0].replace('.', ' ').title())) nickname = sreg_info.get('nickname') if self.groups_to_request and TeamsResponse: teams_response = TeamsResponse.fromSuccessResponse(info) if teams_response: # be careful not to make user a member of any trac groups # not named in groups_to_request teams = set(teams_response.teams ).intersection(self.groups_to_request) if teams: session_attr['openid.teams'] = ','.join(teams) if self.strip_protocol: remote_user = remote_user[remote_user.find('://')+3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and self.re_email_white_list: self.env.log.debug("Filtering email %r through email white-list." % email) allowed = False if email: for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: allowed = False params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) try: result = json.load(urllib.urlopen(url)) if result[self.check_list_key]: if self.check_list_username: cl_username = unicode( result[self.check_list_username]) if not cl_username: raise ValueError("Bad value for username") allowed = True except Exception, ex: self.env.log.error('OpenID check_list failed: %s' % ex) if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime session_attr[self.openid_session_identity_url_key] = info.identity_url if email: session_attr['email'] = email if fullname: session_attr['name'] = fullname self._commit_oidsession(oidsession, req) if self.check_list and self.check_list_username: authname = cl_username elif self.use_nickname_as_authname and nickname: authname = nickname elif session_attr.get('name'): authname = session_attr['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) else: authname = remote_user # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() if self.trust_authname: ds = DetachedSession(self.env, authname) else: # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # session with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) existing_users_and_groups = set( user for user, perm in PermissionSystem(self.env).get_all_permissions()) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. if authname in existing_users_and_groups: # Permissions are already defined for this user continue break ds_identity = ds.get(self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break if ds and (ds.last_visit != 0 or len(ds) > 0): # The user already exists, update team membership # XXX: Should also update name and/or email? (This would # be an API change.) for name in ['openid.teams']: if name in session_attr: ds[name] = session_attr[name] elif name in ds: del ds[name] ds.save() else: # We are creating a new "user". Set attributes on the # current anonymous session. It will be promoted to # the new authenticated session on the next request # (by Session.__init__). # # NB: avoid dict.update here to ensure that # DetachedSession.__getitem__ gets a chance to # normalize values for name, value in session_attr.items(): req.session[name] = value req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.redirect(req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.'