Example #1
0
    def get_for_request(cls, request):
        state = RedisSessionStore(request,
                                  cls.pipeline_name,
                                  ttl=INTEGRATION_EXPIRATION_TTL)
        if not state.is_valid():
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(
                id=state.provider_model_id)

        organization = None
        if state.org_id:
            organization = Organization.objects.get(id=state.org_id)

        provider_key = state.provider_key
        config = state.config

        return cls(
            request,
            organization=organization,
            provider_key=provider_key,
            provider_model=provider_model,
            config=config,
        )
Example #2
0
    def __init__(self,
                 request,
                 provider_key,
                 organization=None,
                 provider_model=None,
                 config=None):
        if config is None:
            config = {}

        self.request = request
        self.organization = organization
        self.state = RedisSessionStore(request, self.pipeline_name)
        self.provider = self.provider_manager.get(provider_key)
        self.provider_model = provider_model

        self.config = config
        self.provider.set_pipeline(self)
        self.provider.set_config(config)

        self.pipeline_views = self.get_pipeline_views()

        # we serialize the pipeline to be ['fqn.PipelineView', ...] which
        # allows us to determine if the pipeline has changed during the auth
        # flow or if the user is somehow circumventing a chunk of it
        pipe_ids = [
            u'{}.{}'.format(type(v).__module__,
                            type(v).__name__) for v in self.pipeline_views
        ]
        self.signature = md5_text(*pipe_ids).hexdigest()
Example #3
0
    def get_for_request(cls, request):
        state = RedisSessionStore(request, cls.pipeline_name)
        if not state.is_valid():
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(id=state.provider_model_id)

        organization = None
        if state.org_id:
            organization = Organization.objects.get(id=state.org_id)

        provider_key = state.provider_key
        config = state.config

        return cls(request, organization=organization, provider_key=provider_key,
                   provider_model=provider_model, config=config)
Example #4
0
    def get_for_request(cls, request):
        state = RedisSessionStore(request, cls.pipeline_name)
        if not state.is_valid():
            return None

        organization_id = state.org_id
        if not organization_id:
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(id=state.provider_model_id)

        organization = Organization.objects.get(id=state.org_id)
        provider_key = state.provider_key
        config = state.config

        return cls(request, organization, provider_key, provider_model, config)
    def test_store_values(self):
        request = HttpRequest()
        request.session = {}

        store = RedisSessionStore(request, 'test-store')
        store.regenerate()

        assert 'store:test-store' in request.session

        store.some_value = 'test_value'
        store2 = RedisSessionStore(request, 'test-store')

        assert store2.is_valid()
        assert store2.some_value == 'test_value'

        with self.assertRaises(AttributeError):
            store.missing_key

        store.clear()
Example #6
0
    def test_store_complex_object(self):
        request = HttpRequest()
        request.session = {}

        store = RedisSessionStore(request, "test-store")
        store.regenerate({"some_value": {"deep_object": "value"}})

        store2 = RedisSessionStore(request, "test-store")

        assert store2.some_value["deep_object"] == "value"

        store.clear()
Example #7
0
    def get_for_request(cls, request):
        from sentry.models import Organization  # Django 1.9 setup issue
        state = RedisSessionStore(request, cls.pipeline_name)
        if not state.is_valid():
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(
                id=state.provider_model_id)

        organization = None
        if state.org_id:
            organization = Organization.objects.get(id=state.org_id)

        provider_key = state.provider_key
        config = state.config

        return cls(request,
                   organization=organization,
                   provider_key=provider_key,
                   provider_model=provider_model,
                   config=config)
    def test_uninitialized_store(self):
        request = HttpRequest()
        request.session = {}

        store = RedisSessionStore(request, 'test-store')

        assert not store.is_valid()
        assert store.get_state() is None
        assert store.some_key is None

        store.setting_but_no_state = 'anything'
        assert store.setting_but_no_state is None

        store.clear()
    def test_store_complex_object(self):
        request = HttpRequest()
        request.session = {}

        store = RedisSessionStore(request, 'test-store')
        store.regenerate({
            'some_value': {'deep_object': 'value'},
        })

        store2 = RedisSessionStore(request, 'test-store')

        assert store2.some_value['deep_object'] == 'value'

        store.clear()
Example #10
0
    def __init__(self, request, organization, provider_key, provider_model=None, config=None):
        if config is None:
            config = {}

        self.request = request
        self.organization = organization
        self.state = RedisSessionStore(request, self.pipeline_name)
        self.provider = self.provider_manager.get(provider_key)
        self.provider_model = provider_model

        self.config = config
        self.provider.set_config(config)

        self.pipeline = self.get_pipeline_views()

        # we serialize the pipeline to be ['fqn.PipelineView', ...] which
        # allows us to determine if the pipeline has changed during the auth
        # flow or if the user is somehow circumventing a chunk of it
        pipe_ids = ['{}.{}'.format(type(v).__module__, type(v).__name__) for v in self.pipeline]
        self.signature = md5_text(*pipe_ids).hexdigest()
Example #11
0
class Pipeline(object):
    """
    Pipeline provides a mechanism to guide the user through a request
    'pipeline', where each view may be completed by calling the ``next_step``
    pipeline method to traverse through the pipe.

    The pipeline works with a PipelineProvider object which provides the
    pipeline views and is made available to the views through the passed in
    pipeline.

    :provider_manager:
    A class property that must be specified to allow for lookup of a provider
    implementation object given it's key.

    :provider_model_cls:
    The Provider model object represents the instance of an object implementing
    the PipelineProvider interface. This is used to look up the instance
    when constructing an in progress pipleine (get_for_request).

    :config:
    A object that specifies additional pipeline and provider runtime
    configurations. An example of usage is for OAuth Identity providers, for
    overriding the scopes. The config object will be passed into the provider
    using the ``set_config`` method.
    """
    pipeline_name = None
    provider_manager = None
    provider_model_cls = None

    @classmethod
    def get_for_request(cls, request):
        state = RedisSessionStore(request, cls.pipeline_name)
        if not state.is_valid():
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(
                id=state.provider_model_id)

        organization = None
        if state.org_id:
            organization = Organization.objects.get(id=state.org_id)

        provider_key = state.provider_key
        config = state.config

        return cls(request,
                   organization=organization,
                   provider_key=provider_key,
                   provider_model=provider_model,
                   config=config)

    def __init__(self,
                 request,
                 provider_key,
                 organization=None,
                 provider_model=None,
                 config=None):
        if config is None:
            config = {}

        self.request = request
        self.organization = organization
        self.state = RedisSessionStore(request, self.pipeline_name)
        self.provider = self.provider_manager.get(provider_key)
        self.provider_model = provider_model

        self.config = config
        self.provider.set_pipeline(self)
        self.provider.set_config(config)

        self.pipeline_views = self.get_pipeline_views()

        # we serialize the pipeline to be ['fqn.PipelineView', ...] which
        # allows us to determine if the pipeline has changed during the auth
        # flow or if the user is somehow circumventing a chunk of it
        pipe_ids = [
            u'{}.{}'.format(type(v).__module__,
                            type(v).__name__) for v in self.pipeline_views
        ]
        self.signature = md5_text(*pipe_ids).hexdigest()

    def get_pipeline_views(self):
        """
        Retrieve the pipeline views from the provider.

        You may wish to override this method to provide views that all
        providers should inherit, or customize the provider method called to
        retrieve the views.
        """
        return self.provider.get_pipeline_views()

    def is_valid(self):
        return self.state.is_valid() and self.state.signature == self.signature

    def initialize(self):
        self.state.regenerate({
            'uid':
            self.request.user.id
            if self.request.user.is_authenticated() else None,
            'provider_model_id':
            self.provider_model.id if self.provider_model else None,
            'provider_key':
            self.provider.key,
            'org_id':
            self.organization.id if self.organization else None,
            'step_index':
            0,
            'signature':
            self.signature,
            'config':
            self.config,
            'data': {},
        })

    def clear_session(self):
        self.state.clear()

    def current_step(self):
        """
        Render the current step.
        """
        step_index = self.state.step_index

        if step_index == len(self.pipeline_views):
            return self.finish_pipeline()

        step = self.pipeline_views[step_index]

        # support late binding steps
        if isinstance(step, LambdaType):
            step = step()

        return step.dispatch(
            request=self.request,
            pipeline=self,
        )

    def error(self, message):
        context = {'error': message}
        return render_to_response('sentry/pipeline-error.html', context,
                                  self.request)

    def next_step(self):
        """
        Render the next step.
        """
        self.state.step_index += 1
        return self.current_step()

    def finish_pipeline(self):
        """
        Called when the pipeline completes the final step.
        """
        raise NotImplementedError

    def bind_state(self, key, value):
        data = self.state.data
        data[key] = value

        self.state.data = data

    def fetch_state(self, key=None):
        return self.state.data if key is None else self.state.data.get(key)
Example #12
0
class Pipeline(object):
    """
    Pipeline provides a mechanism to guide the user through a request
    'pipeline', where each view may be completed by calling the ``next_step``
    pipeline method to traverse through the pipe.

    The pipeline works with a PipelineProvider object which provides the
    pipeline views and is made available to the views through the passed in
    pipeline.

    :provider_manager:
    A class property that must be specified to allow for lookup of a provider
    implementation object given it's key.

    :provider_model_cls:
    The Provider model object represents the instance of an object implementing
    the PipelineProvider interface. This is used to look up the instance
    when constructing an in progress pipleine (get_for_request).

    :config:
    A object that specifies additional pipeline and provider runtime
    configurations. An example of usage is for OAuth Identity providers, for
    overriding the scopes. The config object will be passed into the provider
    using the ``set_config`` method.
    """
    pipeline_name = None
    provider_manager = None
    provider_model_cls = None

    @classmethod
    def get_for_request(cls, request):
        state = RedisSessionStore(request, cls.pipeline_name)
        if not state.is_valid():
            return None

        provider_model = None
        if state.provider_model_id:
            provider_model = cls.provider_model_cls.objects.get(id=state.provider_model_id)

        organization = None
        if state.org_id:
            organization = Organization.objects.get(id=state.org_id)

        provider_key = state.provider_key
        config = state.config

        return cls(request, organization=organization, provider_key=provider_key,
                   provider_model=provider_model, config=config)

    def __init__(self, request, provider_key, organization=None, provider_model=None, config=None):
        if config is None:
            config = {}

        self.request = request
        self.organization = organization
        self.state = RedisSessionStore(request, self.pipeline_name)
        self.provider = self.provider_manager.get(provider_key)
        self.provider_model = provider_model

        self.config = config
        self.provider.set_pipeline(self)
        self.provider.set_config(config)

        self.pipeline_views = self.get_pipeline_views()

        # we serialize the pipeline to be ['fqn.PipelineView', ...] which
        # allows us to determine if the pipeline has changed during the auth
        # flow or if the user is somehow circumventing a chunk of it
        pipe_ids = [u'{}.{}'.format(type(v).__module__, type(v).__name__)
                    for v in self.pipeline_views]
        self.signature = md5_text(*pipe_ids).hexdigest()

    def get_pipeline_views(self):
        """
        Retrieve the pipeline views from the provider.

        You may wish to override this method to provide views that all
        providers should inherit, or customize the provider method called to
        retrieve the views.
        """
        return self.provider.get_pipeline_views()

    def is_valid(self):
        return self.state.is_valid() and self.state.signature == self.signature

    def initialize(self):
        self.state.regenerate({
            'uid': self.request.user.id if self.request.user.is_authenticated() else None,
            'provider_model_id': self.provider_model.id if self.provider_model else None,
            'provider_key': self.provider.key,
            'org_id': self.organization.id if self.organization else None,
            'step_index': 0,
            'signature': self.signature,
            'config': self.config,
            'data': {},
        })

    def clear_session(self):
        self.state.clear()

    def current_step(self):
        """
        Render the current step.
        """
        step_index = self.state.step_index

        if step_index == len(self.pipeline_views):
            return self.finish_pipeline()

        step = self.pipeline_views[step_index]

        # support late binding steps
        if isinstance(step, LambdaType):
            step = step()

        return step.dispatch(
            request=self.request,
            pipeline=self,
        )

    def error(self, message):
        context = {'error': message}
        return render_to_response('sentry/pipeline-error.html', context, self.request)

    def next_step(self):
        """
        Render the next step.
        """
        self.state.step_index += 1
        return self.current_step()

    def finish_pipeline(self):
        """
        Called when the pipeline completes the final step.
        """
        raise NotImplementedError

    def bind_state(self, key, value):
        data = self.state.data
        data[key] = value

        self.state.data = data

    def fetch_state(self, key=None):
        return self.state.data if key is None else self.state.data.get(key)