def get_groups(self, env, token):
groups = None<EOL>memcache_client = cache_from_env(env)<EOL>if memcache_client:<EOL><INDENT>memcache_key = '<STR_LIT>' % (self.reseller_prefix, token)<EOL>cached_auth_data = memcache_client.get(memcache_key)<EOL>if cached_auth_data:<EOL><INDENT>expires, groups = cached_auth_data<EOL>if expires < time():<EOL><INDENT>groups = None<EOL><DEDENT><DEDENT><DEDENT>s3_auth_details = env.get('<STR_LIT>')<EOL>if s3_auth_details:<EOL><INDENT>if not self.s3_support:<EOL><INDENT>self.logger.warning('<STR_LIT>')<EOL>return None<EOL><DEDENT>if self.swauth_remote:<EOL><INDENT>self.logger.warning('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>return None<EOL><DEDENT>try:<EOL><INDENT>account, user = s3_auth_details['<STR_LIT>'].split('<STR_LIT::>', <NUM_LIT:1>)<EOL>signature_from_user = s3_auth_details['<STR_LIT>']<EOL>msg = s3_auth_details['<STR_LIT>']<EOL><DEDENT>except Exception:<EOL><INDENT>self.logger.debug(<EOL>'<STR_LIT>' %<EOL>(s3_auth_details, ))<EOL>return None<EOL><DEDENT>path = quote('<STR_LIT>' % (self.auth_account, account, user))<EOL>resp = self.make_pre_authed_request(<EOL>env, '<STR_LIT:GET>', path).get_response(self.app)<EOL>if resp.status_int // <NUM_LIT:100> != <NUM_LIT:2>:<EOL><INDENT>return None<EOL><DEDENT>if '<STR_LIT>' in resp.headers:<EOL><INDENT>account_id = resp.headers['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>path = quote('<STR_LIT>' % (self.auth_account, account))<EOL>resp2 = self.make_pre_authed_request(<EOL>env, '<STR_LIT>', path).get_response(self.app)<EOL>if resp2.status_int // <NUM_LIT:100> != <NUM_LIT:2>:<EOL><INDENT>return None<EOL><DEDENT>account_id = resp2.headers['<STR_LIT>']<EOL><DEDENT>path = env['<STR_LIT>']<EOL>env['<STR_LIT>'] = path.replace("<STR_LIT>" % (account, user),<EOL>account_id, <NUM_LIT:1>)<EOL>detail = json.loads(resp.body)<EOL>if detail:<EOL><INDENT>creds = detail.get('<STR_LIT>')<EOL>try:<EOL><INDENT>auth_encoder, creds_dict =swauth.authtypes.validate_creds(creds)<EOL><DEDENT>except ValueError as e:<EOL><INDENT>self.logger.error('<STR_LIT:%s>' % e.args[<NUM_LIT:0>])<EOL>return None<EOL><DEDENT><DEDENT>password = creds_dict['<STR_LIT>']<EOL>if isinstance(password, six.text_type):<EOL><INDENT>password = password.encode('<STR_LIT:utf-8>')<EOL><DEDENT>if isinstance(msg, six.text_type):<EOL><INDENT>msg = msg.encode('<STR_LIT:utf-8>')<EOL><DEDENT>valid_signature = base64.encodestring(hmac.new(<EOL>password, msg, sha1).digest()).strip()<EOL>if signature_from_user != valid_signature:<EOL><INDENT>return None<EOL><DEDENT>groups = [g['<STR_LIT:name>'] for g in detail['<STR_LIT>']]<EOL>if '<STR_LIT>' in groups:<EOL><INDENT>groups.remove('<STR_LIT>')<EOL>groups.append(account_id)<EOL><DEDENT>groups = '<STR_LIT:U+002C>'.join(groups)<EOL>return groups<EOL><DEDENT>if not groups:<EOL><INDENT>if self.swauth_remote:<EOL><INDENT>with Timeout(self.swauth_remote_timeout):<EOL><INDENT>conn = http_connect(self.swauth_remote_parsed.hostname,<EOL>self.swauth_remote_parsed.port, '<STR_LIT:GET>',<EOL>'<STR_LIT>' % (self.swauth_remote_parsed.path,<EOL>quote(token)),<EOL>ssl=(self.swauth_remote_parsed.scheme == '<STR_LIT>'))<EOL>resp = conn.getresponse()<EOL>resp.read()<EOL>conn.close()<EOL><DEDENT>if resp.status // <NUM_LIT:100> != <NUM_LIT:2>:<EOL><INDENT>return None<EOL><DEDENT>expires_from_now = float(resp.getheader('<STR_LIT>'))<EOL>groups = resp.getheader('<STR_LIT>')<EOL>if memcache_client:<EOL><INDENT>memcache_client.set(<EOL>memcache_key, (time() + expires_from_now, groups),<EOL>time=expires_from_now)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>object_name = self._get_concealed_token(token)<EOL>path = quote('<STR_LIT>' %<EOL>(self.auth_account, object_name[-<NUM_LIT:1>], object_name))<EOL>resp = self.make_pre_authed_request(<EOL>env, '<STR_LIT:GET>', path).get_response(self.app)<EOL>if resp.status_int // <NUM_LIT:100> != <NUM_LIT:2>:<EOL><INDENT>return None<EOL><DEDENT>detail = json.loads(resp.body)<EOL>if detail['<STR_LIT>'] < time():<EOL><INDENT>self.make_pre_authed_request(<EOL>env, '<STR_LIT>', path).get_response(self.app)<EOL>return None<EOL><DEDENT>groups = [g['<STR_LIT:name>'] for g in detail['<STR_LIT>']]<EOL>if '<STR_LIT>' in groups:<EOL><INDENT>groups.remove('<STR_LIT>')<EOL>groups.append(detail['<STR_LIT>'])<EOL><DEDENT>groups = '<STR_LIT:U+002C>'.join(groups)<EOL>if memcache_client:<EOL><INDENT>memcache_client.set(<EOL>memcache_key,<EOL>(detail['<STR_LIT>'], groups),<EOL>time=float(detail['<STR_LIT>'] - time()))<EOL><DEDENT><DEDENT><DEDENT>return groups<EOL>
Get groups for the given token.

        :param env: The current WSGI environment dictionary.
        :param token: Token to validate and return a group string for.

        :returns: None if the token is invalid or a string containing a comma
                  separated list of groups the authenticated user is a member
                  of. The first group in the list is also considered a unique
                  identifier for that user.