예제 #1
0
    def receive(self, content, **kwargs):
        tenant_pk = self.message.channel_session.get('tenant')
        logger.info('tenant pk: {}'.format(tenant_pk))

        if tenant_pk is None:
            logger.error('TransactionConsumer tenant not in session')
            return

        try:
            tenant = get_tenant_model().objects.get(
                pk=tenant_pk
            )
        except get_tenant_model().DoesNotExist:
            return

        with tenant_context(tenant):
            more_blocks = Block.objects.exclude(
                height__isnull=True
            ).filter(
                height__lt=content.get('height')
            ).order_by(
                '-height'
            )[:20]

            kwargs.get('multiplexer').send(
                {
                    "more_blocks": [
                        block.serialize() for block in more_blocks
                    ]
                }
            )
예제 #2
0
    def migrate_tenant_apps(self, schema_name=None):
        self._save_south_settings()

        apps = self.tenant_apps or self.installed_apps
        self._set_managed_apps(included_apps=apps,
                               excluded_apps=self.shared_apps)

        migrate_command = MigrateCommand()
        if schema_name:
            print self.style.NOTICE("=== Running migrate for schema: %s" %
                                    schema_name)
            connection.set_schema_to_public()
            sync_tenant = get_tenant_model().objects.filter(
                schema_name=schema_name).get()
            connection.set_tenant(sync_tenant, include_public=False)
            migrate_command.execute(**self.options)
        else:
            public_schema_name = get_public_schema_name()
            tenant_schemas_count = get_tenant_model().objects.exclude(
                schema_name=public_schema_name).count()
            if not tenant_schemas_count:
                print self.style.NOTICE("No tenants found")

            for tenant_schema in get_tenant_model().objects.exclude(
                    schema_name=public_schema_name).all():
                Migrations._dependencies_done = False  # very important, the dependencies need to be purged from cache
                print self.style.NOTICE("=== Running migrate for schema %s" %
                                        tenant_schema.schema_name)
                connection.set_tenant(tenant_schema, include_public=False)
                migrate_command.execute(**self.options)

        self._restore_south_settings()
예제 #3
0
    def receive(self, content, multiplexer, **kwargs):
        logger.info(multiplexer)
        tenant_pk = self.message.channel_session.get('tenant')
        logger.info('tenant pk: {}'.format(tenant_pk))

        if tenant_pk is None:
            logger.error('TransactionConsumer tenant not in session')
            logger.info(self.message.content)
            return

        try:
            tenant = get_tenant_model().objects.get(
                pk=tenant_pk
            )
        except get_tenant_model().DoesNotExist:
            return

        with tenant_context(tenant):
            try:
                block = Block.objects.get(height=int(content.get('height')))
            except Block.DoesNotExist:
                return

            multiplexer.send(
                {
                    'transactions': [
                        tx.serialize() for tx in block.transactions.all()
                    ]
                }
            )
    def migrate_tenant_apps(self, schema_name=None):
        self._save_south_settings()

        apps = self.tenant_apps or self.installed_apps
        self._set_managed_apps(included_apps=apps, excluded_apps=self.shared_apps)

        syncdb_command = MigrateCommand()
        if schema_name:
            print self.style.NOTICE("=== Running migrate for schema: %s" % schema_name)
            connection.set_schema_to_public()
            sync_tenant = get_tenant_model().objects.filter(schema_name=schema_name).get()
            connection.set_tenant(sync_tenant, include_public=False)
            syncdb_command.execute(**self.options)
        else:
            public_schema_name = get_public_schema_name()
            tenant_schemas_count = get_tenant_model().objects.exclude(schema_name=public_schema_name).count()
            if not tenant_schemas_count:
                print self.style.NOTICE("No tenants found")

            for tenant_schema in get_tenant_model().objects.exclude(schema_name=public_schema_name).all():
                Migrations._dependencies_done = False  # very important, the dependencies need to be purged from cache
                print self.style.NOTICE("=== Running migrate for schema %s" % tenant_schema.schema_name)
                connection.set_tenant(tenant_schema, include_public=False)
                syncdb_command.execute(**self.options)

        self._restore_south_settings()
예제 #5
0
    def receive(self, content, multiplexer, **kwargs):
        logger.info(multiplexer)
        logger.info(self.message)
        tenant_pk = self.message.channel_session.get('tenant')
        logger.info('tenant pk: {}'.format(tenant_pk))

        if tenant_pk is None:
            logger.error('TransactionConsumer tenant not in session')
            logger.info(self.message.channel)
            return

        try:
            tenant = get_tenant_model().objects.get(
                pk=tenant_pk
            )
        except get_tenant_model().DoesNotExist:
            return

        with tenant_context(tenant):
            try:
                block = Block.objects.get(height=content.get('height'))
            except Block.DoesNotExist:
                return

            multiplexer.send(
                {
                    'block': block.serialize(),
                    'next_block': block.next_block.height if block.next_block else None,
                    'previous_block': block.previous_block.height if block.previous_block else None,
                }
            )
예제 #6
0
    def migrate_tenant_apps(self, schema_name=None):
        self._save_south_settings()

        apps = self.tenant_apps or self.installed_apps
        self._set_managed_apps(included_apps=apps,
                               excluded_apps=self.shared_apps)

        if schema_name:
            self._notice("=== Running migrate for schema: %s" % schema_name)
            connection.set_schema_to_public()
            tenant = get_tenant_model().objects.get(schema_name=schema_name)
            self._migrate_schema(tenant)
        else:
            all_tenants = get_tenant_model().objects.exclude(
                schema_name=get_public_schema_name())
            if not all_tenants:
                self._notice("No tenants found")

            for tenant in all_tenants:
                Migrations._dependencies_done = False  # very important, the dependencies need to be purged from cache
                self._notice("=== Running migrate for schema %s" %
                             tenant.schema_name)
                self._migrate_schema(tenant)

        self._restore_south_settings()
    def sync_tenant_apps(self, schema_name=None):
        ContentType.objects.clear_cache()

        apps = self.tenant_apps or self.installed_apps
        self._set_managed_apps(apps)
        syncdb_command = SyncdbCommand()
        if schema_name:
            print self.style.NOTICE("=== Running syncdb for schema: %s" %
                                    schema_name)
            sync_tenant = get_tenant_model().objects.filter(
                schema_name=schema_name).get()
            connection.set_tenant(sync_tenant, include_public=False)
            syncdb_command.execute(**self.options)
        else:
            public_schema_name = get_public_schema_name()
            tenant_schemas_count = get_tenant_model().objects.exclude(
                schema_name=public_schema_name).count()
            if not tenant_schemas_count:
                print self.style.NOTICE("No tenants found")

            for tenant_schema in get_tenant_model().objects.exclude(
                    schema_name=public_schema_name).all():
                print self.style.NOTICE("=== Running syncdb for schema %s" %
                                        tenant_schema.schema_name)
                connection.set_tenant(tenant_schema, include_public=False)
                syncdb_command.execute(**self.options)
예제 #8
0
 def handle(self, *args, **options):
     """
     Iterates a command over all registered schemata.
     """
     if options['schema_name']:
         # only run on a particular schema
         connection.set_schema_to_public()
         self.execute_command(get_tenant_model().objects.get(schema_name=options['schema_name']), self.COMMAND_NAME, *args, **options)
     else:
         for tenant in get_tenant_model().objects.all():
             self.execute_command(tenant, self.COMMAND_NAME, *args, **options)
    def sync_tenant_apps(self, schema_name=None):
        if schema_name:
            tenant = get_tenant_model().objects.filter(schema_name=schema_name).get()
            self._sync_tenant(tenant)
        else:
            all_tenants = get_tenant_model().objects.exclude(schema_name=get_public_schema_name())
            if not all_tenants:
                self._notice("No tenants found!")

            for tenant in all_tenants:
                self._sync_tenant(tenant)
예제 #10
0
 def handle(self, *args, **options):
     """
     Iterates a command over all registered schemata.
     """
     if options['schema_name']:
         # only run on a particular schema
         connection.set_schema_to_public()
         self.execute_command(get_tenant_model().objects.get(schema_name=options['schema_name']), self.COMMAND_NAME, *args, **options)
     else:
         for tenant in get_tenant_model().objects.all():
             self.execute_command(tenant, self.COMMAND_NAME, *args, **options)
예제 #11
0
    def load_fixtures(self, client_name):
        from django.db import connection

        try:
            tenant = get_tenant_model().objects.get(client_name=client_name)
            connection.set_tenant(tenant)
            call_command('loaddata', 'skills')
            call_command('loaddata', 'redirects')
            call_command('loaddata', 'project_data')
            call_command('loaddata', 'geo_data')
        except get_tenant_model().DoesNotExist:
            self.stdout.write("Client not found. Skipping loading fixtures")
예제 #12
0
    def load_fixtures(self, client_name):
        from django.db import connection

        try:
            tenant = get_tenant_model().objects.get(client_name=client_name)
            connection.set_tenant(tenant)
            call_command('loaddata', 'skills')
            call_command('loaddata', 'redirects')
            call_command('loaddata', 'project_data')
            call_command('loaddata', 'geo_data')
        except get_tenant_model().DoesNotExist:
            self.stdout.write("Client not found. Skipping loading fixtures")
예제 #13
0
    def sync_tenant_apps(self, schema_name=None):
        if schema_name:
            tenant = get_tenant_model().objects.filter(
                schema_name=schema_name).get()
            self._sync_tenant(tenant)
        else:
            all_tenants = get_tenant_model().objects.exclude(
                schema_name=get_public_schema_name())
            if not all_tenants:
                self._notice("No tenants found!")

            for tenant in all_tenants:
                self._sync_tenant(tenant)
예제 #14
0
    def handle(self, *args, **kwargs):
        tenant = connection.tenant
        if not tenant and kwargs['schema']:
            tenant = get_tenant_model().objects.get(
                schema_name=kwargs['schema'])
        print "Exporting %s..." % tenant

        connection.set_tenant(tenant, include_public=False)

        datadir = kwargs['datadir']

        dt = None
        pattern = '^([a-z]+):(\d+)$'
        if 'time' in kwargs and kwargs['time'] and re.search(
                pattern, kwargs['time']):
            tdict = eval(re.sub(pattern, '{"\\1": \\2}', kwargs['time']))
            dt = datetime.timedelta(**tdict)
            print "from %s" % dt

        if not os.path.exists(datadir):
            os.mkdir(datadir)

        mod = __import__('resources')

        for m in mod.__dict__.items():
            if 'Resource' in m[0]:
                mname = m[0]
                print mname
                res = m[1]
                if dt and mname in querysets:
                    res.dt = dt
                    res.get_queryset = querysets[mname]
                dataset = res().export()
                f = open(os.path.join(datadir, '%s.csv' % mname), 'w')
                f.write(dataset.csv)
예제 #15
0
    def setUpClass(cls):
        # create a tenant
        tenant_domain = 'tenant.test.com'
        cls.tenant = get_tenant_model()(domain_url=tenant_domain, schema_name='test')
        cls.tenant.save()

        connection.set_tenant(cls.tenant)
예제 #16
0
    def process_request(self, request):
        # Connection needs first to be at the public schema, as this is where
        # the tenant metadata is stored.
        connection.set_schema_to_public()

        hostname = self.hostname_from_request(request)
        TenantModel = get_tenant_model()

        try:
            # get_tenant must be implemented by extending this class.
            tenant = self.get_tenant(TenantModel, hostname, request)
            assert isinstance(tenant, TenantModel)
        except TenantModel.DoesNotExist:
            raise self.TENANT_NOT_FOUND_EXCEPTION(
                'No tenant for {!r}'.format(request.get_host()))
        except AssertionError:
            raise self.TENANT_NOT_FOUND_EXCEPTION(
                'Invalid tenant {!r}'.format(request.tenant))

        request.tenant = tenant
        connection.set_tenant(request.tenant)

        # Content type can no longer be cached as public and tenant schemas
        # have different models. If someone wants to change this, the cache
        # needs to be separated between public and shared schemas. If this
        # cache isn't cleared, this can cause permission problems. For example,
        # on public, a particular model has id 14, but on the tenants it has
        # the id 15. if 14 is cached instead of 15, the permissions for the
        # wrong model will be fetched.
        ContentType.objects.clear_cache()

        # Do we have a public-specific urlconf?
        if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #17
0
    def connect(self, message, **kwargs):
        try:
            tenant = get_tenant_model().objects.get(
                domain_url=get_host(message.content)
            )
        except get_tenant_model().DoesNotExist:
            logger.error(
                'no tenant found for {}'.format(
                    get_host(message.content)
                )
            )
            message.reply_channel.send({"close": True})
            return

        message.channel_session['tenant'] = tenant.pk
        super().connect(message, **kwargs)
    def _get_tenant(self, request, allow_public=None):
        tenant_id = request.session.get('active_tenant')
        tenant = None
        TenantModel = get_tenant_model()
        if tenant_id is not None:
            try:
                tenant = TenantModel.objects.get(pk=tenant_id)
            except TenantModel.DoesNotExist:
                del request.session['active_tenant']
                tenant = None
        if tenant is None:
            tenant = connection.tenant

        if tenant.schema_name == get_public_schema_name():
            allow_public = allow_public if allow_public is not None else (
                self.model._meta.app_label in app_labels(settings.TENANT_APPS))
            if not allow_public:
                return None
            tenant = TenantModel.objects.exclude(
                schema_name=get_public_schema_name()).first()
            if tenant:
                self.message_user(request,
                                  "This model does not exist in public schema."
                                  " Falling into any first tenant.",
                                  level=messages.WARNING)

        return tenant
class TenantForm(forms.Form):
    active_tenant = forms.ModelChoiceField(
        get_tenant_model().objects.all(),
        empty_label=None,
        widget=forms.Select(attrs={"onChange": 'this.form.submit();'}),
        label=_('Tenant:'),
    )
예제 #20
0
    def setUpClass(cls):
        # create a tenant
        tenant_domain = "testserver"
        cls.tenant = get_tenant_model()(domain_url=tenant_domain, schema_name="test")
        cls.tenant.save(verbosity=0)  # todo: is there any way to get the verbosity from the test command here?

        connection.set_tenant(cls.tenant)
    def process_request(self, request):
        # Connection needs first to be at the public schema, as this is where
        # the tenant metadata is stored.
        connection.set_schema_to_public()

        hostname = self.hostname_from_request(request)
        TenantModel = get_tenant_model()

        try:
            # get_tenant must be implemented by extending this class.
            tenant = self.get_tenant(TenantModel, hostname, request)
            assert isinstance(tenant, TenantModel)
        except TenantModel.DoesNotExist:
            raise self.TENANT_NOT_FOUND_EXCEPTION("No tenant for {!r}".format(
                request.get_host()))
        except AssertionError:
            raise self.TENANT_NOT_FOUND_EXCEPTION("Invalid tenant {!r}".format(
                request.tenant))

        request.tenant = tenant
        connection.set_tenant(request.tenant)

        # Do we have a public-specific urlconf?
        if (hasattr(settings, "PUBLIC_SCHEMA_URLCONF")
                and request.tenant.schema_name == get_public_schema_name()):
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #22
0
    def process_request(self, request):
        """
        Resets to public schema

        Some nasty weird bugs happened at the production environment without this call.
        connection.pg_thread.schema_name would already be set and then terrible errors
        would occur. Any idea why? My theory is django implements connection as some sort
        of threading local variable.
        """
        connection.set_schema_to_public()
        hostname_without_port = remove_www_and_dev(request.get_host().split(':')[0])

        TenantModel = get_tenant_model()
        request.tenant = get_object_or_404(TenantModel, domain_url=hostname_without_port)
        connection.set_tenant(request.tenant)

        # content type can no longer be cached as public and tenant schemas have different
        # models. if someone wants to change this, the cache needs to be separated between
        # public and shared schemas. if this cache isn't cleared, this can cause permission
        # problems. for example, on public, a particular model has id 14, but on the tenants
        # it has the id 15. if 14 is cached instead of 15, the permissions for the wrong
        # model will be fetched.
        ContentType.objects.clear_cache()

        # do we have a public-specific token?
        if hasattr(settings, 'PUBLIC_SCHEMA_URL_TOKEN') and request.tenant.schema_name == get_public_schema_name():
            request.path_info = settings.PUBLIC_SCHEMA_URL_TOKEN + request.path_info
예제 #23
0
    def get_context_data(self, **kwargs):
        form = kwargs.get('form')

        if form and form.is_valid():
            start = form.get_start()
            stop = form.get_stop()
            tenant = form.cleaned_data.get('tenant', None)

            if tenant:
                connection.set_tenant(tenant)
                header = ' - {}'.format(tenant.name)
                statistics = get_accounting_statistics(start, stop)
            else:
                header = ' - All tenants'
                statistics = mydict()

                for tenant in get_tenant_model().objects.all():
                    connection.set_tenant(tenant)
                    statistics += get_accounting_statistics(start, stop)
        else:
            header = ''
            statistics = {}

        context = super(MultiTenantAccountingOverviewView, self).get_context_data(**kwargs)

        context.update({
             'app_label': 'accounting',
             'title': _('Accountancy Overview') + header,
             'statistics': statistics,
        })
        return context
예제 #24
0
    def get_tenant_from_options_or_interactive(self, **options):
        TenantModel = get_tenant_model()
        all_tenants = TenantModel.objects.all()

        if not all_tenants:
            raise CommandError("""There are no tenants in the system.
To learn how create a tenant, see:
https://django-tenant-schemas.readthedocs.org/en/latest/use.html#creating-a-tenant"""
                               )

        if options.get('schema_name'):
            tenant_schema = options['schema_name']
        else:
            while True:
                tenant_schema = input(
                    "Enter Tenant Schema ('?' to list schemas): ")
                if tenant_schema == '?':
                    print('\n'.join([
                        "%s - %s" % (
                            t.schema_name,
                            t.domain_url,
                        ) for t in all_tenants
                    ]))
                else:
                    break

        if tenant_schema not in [t.schema_name for t in all_tenants]:
            raise CommandError("Invalid tenant schema, '%s'" %
                               (tenant_schema, ))

        return TenantModel.objects.get(schema_name=tenant_schema)
예제 #25
0
    def process_request(self, request, *args, **kwargs):

        db = self.get_database(request)
        connections[db].set_schema_to_public()

        request_cfg.db = db
        hostname = self.hostname_from_request(request)
        TenantModel = get_tenant_model()
        try:
            # get_tenant must be implemented by extending this class.
            tenant = self.get_tenant(TenantModel, hostname, request)
            assert isinstance(tenant, TenantModel)
        except TenantModel.DoesNotExist:
            raise self.TENANT_NOT_FOUND_EXCEPTION('No tenant for {!r}'.format(
                request.get_host()))
        except AssertionError:
            raise self.TENANT_NOT_FOUND_EXCEPTION('Invalid tenant {!r}'.format(
                request.tenant))

        request.tenant = tenant
        connections[db].set_tenant(request.tenant)

        # Do we have a public-specific urlconf?
        if hasattr(
                settings, 'PUBLIC_SCHEMA_URLCONF'
        ) and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #26
0
    def process_request(self, request):
        connection.set_schema_to_public()
        hostname_without_port = remove_www_and_dev(
            request.get_host().split(':')[0])

        TenantModel = get_tenant_model()

        try:
            request.tenant = TenantModel.objects.get(
                domain_url=hostname_without_port)
        except utils.DatabaseError:
            request.urlconf = settings.ROOT_URLCONF
            return
        except TenantModel.DoesNotExist:
            if hostname_without_port in ("127.0.0.1", "localhost"):
                request.urlconf = settings.ROOT_URLCONF
                return
            else:
                raise Http404

        connection.set_tenant(request.tenant)
        # ContentType.objects.clear_cache()
        # Session.objects.all().delete()

        if hasattr(
                settings, 'ROOT_URLCONF'
        ) and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.ROOT_URLCONF
예제 #27
0
    def get_tenant_from_options_or_interactive(self, **options):
        TenantModel = get_tenant_model()
        all_tenants = TenantModel.objects.all()

        if not all_tenants:
            raise CommandError("""There are no tenants in the system.
To learn how create a tenant, see:
https://django-multitenants.readthedocs.org/en/latest/use.html#creating-a-tenant""")

        if options.get('schema_name'):
            tenant_schema = options['schema_name']
        else:
            while True:
                tenant_schema = input(
                    "Enter Tenant Schema ('?' to list schemas): ")
                if tenant_schema == '?':
                    print(
                        '\n'.join(["%s - %s" % (t.schema_name, t.domain_url,) for t in all_tenants]))
                else:
                    break

        if tenant_schema not in [t.schema_name for t in all_tenants]:
            raise CommandError(
                "Invalid tenant schema, '%s'" % (tenant_schema,))

        return TenantModel.objects.get(schema_name=tenant_schema)
예제 #28
0
    def process_request(self, request):
        connection.set_schema_to_public()
        hostname_without_port = remove_www_and_dev(
            request.get_host().split(':')[0])

        TenantModel = get_tenant_model()

        try:
            request.tenant = TenantModel.objects.get(
                domain_url=hostname_without_port)

        except utils.DatabaseError:
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
            return
        except TenantModel.DoesNotExist:
            if hostname_without_port in ("127.0.0.1", "localhost", "multidemo.com"):
                request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
                return
            else:
                raise Http404

        connection.set_tenant(request.tenant)
        ContentType.objects.clear_cache()

        if hasattr(settings, "PUBLIC_SCHEMA_URLCONF") and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF

        if hasattr(settings, "API_URLCONF") and request.tenant.name == 'API':
            self.urlconf = settings.API_URLCONF
예제 #29
0
    def process_request(self, request):
        """
        Resets to public schema

        Some nasty weird bugs happened at the production environment without this call.
        connection.pg_thread.schema_name would already be set and then terrible errors
        would occur. Any idea why? My theory is django implements connection as some sort
        of threading local variable.
        """
        connection.set_schema_to_public()
        hostname_without_port = remove_www_and_dev(
            request.get_host().split(':')[0])

        TenantModel = get_tenant_model()
        request.tenant = get_object_or_404(TenantModel,
                                           domain_url=hostname_without_port)
        connection.set_tenant(request.tenant)

        # do we have tenant-specific URLs?
        if hasattr(
                settings, 'PUBLIC_SCHEMA_URL_TOKEN'
        ) and request.tenant.schema_name == "public" and request.path_info[
                -1] == '/':
            # we are not at the public schema, manually alter routing to schema-dependent urls
            request.path_info = settings.PUBLIC_SCHEMA_URL_TOKEN + request.path_info
    def process_request(self, request):
        # Connection needs first to be at the public schema, as this is where
        # the tenant metadata is stored.
        connection.set_schema_to_public()
        hostname = self.hostname_from_request(request)

        tenant_model = get_tenant_model()
        try:
            request.tenant = tenant_model.objects.get(domain_url=hostname)
            connection.set_tenant(request.tenant)
        except tenant_model.DoesNotExist:
            pass

        # Content type can no longer be cached as public and tenant schemas
        # have different models. If someone wants to change this, the cache
        # needs to be separated between public and shared schemas. If this
        # cache isn't cleared, this can cause permission problems. For example,
        # on public, a particular model has id 14, but on the tenants it has
        # the id 15. if 14 is cached instead of 15, the permissions for the
        # wrong model will be fetched.
        ContentType.objects.clear_cache()

        # Do we have a public-specific urlconf?
        if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #31
0
    def setUp(self):
        super(TestMultiTenant, self).setUp()

        now = timezone.now()

        self.init_projects()
        self.tenant1 = connection.tenant

        # Create a project for the main tenant
        self.project = ProjectFactory.create(
            status=ProjectPhase.objects.get(slug='campaign'),
            deadline=now - timezone.timedelta(days=5),
            campaign_started=now - timezone.timedelta(days=5),
            organization=None,
            amount_asked=0)

        # Create a second tenant
        self.tenant2 = get_tenant_model().objects.get(schema_name='test2')
        connection.set_tenant(self.tenant2)

        self.init_projects()
        self.project2 = ProjectFactory.create(
            status=ProjectPhase.objects.get(slug='campaign'),
            deadline=now - timezone.timedelta(days=5),
            campaign_started=now - timezone.timedelta(days=5),
            organization=None,
            amount_asked=0)
예제 #32
0
    def handle(self, *args, **options):
        super(migrate_schemas.Command, self).handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        executor = get_executor(codename=self.executor)(self.args,
                                                        self.options)

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        if self.sync_public:
            executor.run_migrations(tenants=[self.schema_name])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name):
                    msg = f"Schema {self.schema_name} does not exist, skipping."
                    LOG.info(msg)
                else:
                    tenants = [self.schema_name]
            else:
                from django.db.models.expressions import RawSQL

                tenant_model = get_tenant_model()
                tenants = list(
                    tenant_model.objects.filter(schema_name__in=RawSQL(
                        """
                                SELECT nspname::text
                                FROM pg_catalog.pg_namespace
                                WHERE nspname = %s
                                    OR nspname ~ '^acct'
                            """,
                        (tenant_model._TEMPLATE_SCHEMA, ),
                    )).values_list("schema_name", flat=True))
            executor.run_migrations(tenants=tenants)
예제 #33
0
    def process_request(self, request):  # Wei-Lin
        connection.set_schema_to_public()
        hostname_without_port = filter_url_path(request.path)

        if hostname_without_port in self.filter_first_path:
            print("public schema")
        else:

            TenantModel = get_tenant_model()

            try:
                request.tenant = TenantModel.objects.get(
                    schema_name=hostname_without_port)
            except utils.DatabaseError:
                request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
                return
            except TenantModel.DoesNotExist:
                if hostname_without_port in ("127.0.0.1", "localhost"):
                    request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
                    return
                else:
                    raise Http404

            connection.set_tenant(request.tenant)
        ContentType.objects.clear_cache()

        if hasattr(
                settings, 'PUBLIC_SCHEMA_URLCONF'
        ) and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #34
0
    def setUpClass(cls):
        cls.sync_shared()
        tenant_domain = 'tenant.test.com'
        cls.tenant = get_tenant_model()(domain_url=tenant_domain, schema_name='test')
        cls.tenant.save(verbosity=0)  # todo: is there any way to get the verbosity from the test command here?

        connection.set_tenant(cls.tenant)
예제 #35
0
    def setUpClass(cls):
        cls.sync_shared()
        tenant_domain = 'tenant.test.com'

        TenantModel = get_tenant_model()
        try:
            cls.tenant = TenantModel.objects.get(domain_url=tenant_domain, schema_name='test')
        except:
            cls.tenant = TenantModel(domain_url=tenant_domain, schema_name='test')
            cls.tenant.save(verbosity=0)

        connection.set_tenant(cls.tenant)

        if cls.fixtures:
            for db_name in cls._databases_names(include_mirrors=False):
                    try:
                        call_command('loaddata', *cls.fixtures, **{
                            'verbosity': 0,
                            'commit': False,
                            'database': db_name,
                        })
                    except Exception:
                        cls._rollback_atomics(cls.cls_atomics)
                        raise
        try:
            cls.setUpTestData()
        except Exception:
            cls._rollback_atomics(cls.cls_atomics)
            raise
예제 #36
0
def make_tenant(schema='test', domain='tenant.test.com', username='******'):
    """Returns a tuple:  (a tenant schema, an administrative user for it).

    `schema`:   Schema name
    `domain`:   Domain for the tenant site
    `username`: Username to be admin of the site

    Both user and tenant are created if they don't already exist, and the db
    connection is set to that tenant.  Logs to tests.util, level INFO.
    Tenant creation is conditional because it requires significant time.
    """
    TenantTestCase.sync_shared()
    # create or get the user
    user, created = User.objects.get_or_create(username=username)
    if created:
        logger.info("Created user '{}'.".format(user))
    else:
        logger.info("User '{}' exists, not creating it.".format(user))
    # create or get the tenant
    goc = get_tenant_model().objects.get_or_create
    d = {'domain_url': domain, 'schema_name': schema, 'user': user}
    tenant, created = goc(schema_name=schema, defaults=d)
    if created:
        msg = "No schema named '{}' detected; creating one"
        logger.info(msg.format(schema))
        tenant.create_schema(check_if_exists=True)
    else:
        logger.info("Tenant with schema name '{}' found".format(schema))
    connection.set_tenant(tenant)

    return (user, tenant)
예제 #37
0
    def process_request(self, request):
        # Connection needs first to be at the public schema, as this is where
        # the tenant metadata is stored.
        connection.set_schema_to_public()
        hostname = self.hostname_from_request(request)

        TenantModel = get_tenant_model()

        try:
            request.tenant = TenantModel.get_for_domain(hostname)
            connection.set_tenant(request.tenant)
        except TenantModel.DoesNotExist:
            raise self.TENANT_NOT_FOUND_EXCEPTION(
                'No tenant for hostname "%s"' % hostname)

        # Content type can no longer be cached as public and tenant schemas
        # have different models. If someone wants to change this, the cache
        # needs to be separated between public and shared schemas. If this
        # cache isn't cleared, this can cause permission problems. For example,
        # on public, a particular model has id 14, but on the tenants it has
        # the id 15. if 14 is cached instead of 15, the permissions for the
        # wrong model will be fetched.
        ContentType.objects.clear_cache()

        # Do we have a public-specific urlconf?
        if hasattr(
                settings, 'PUBLIC_SCHEMA_URLCONF'
        ) and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
    def handle(self, *args, **options):
        super(Command, self).handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        executor = get_executor(codename=self.executor)(self.args, self.options)

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        if self.sync_public:
            executor.run_migrations(tenants=[self.schema_name])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name):
                    raise MigrationSchemaMissing(
                        'Schema "{}" does not exist'.format(self.schema_name)
                    )
                else:
                    tenants = [self.schema_name]
            else:
                tenants = (
                    get_tenant_model()
                        .objects.exclude(schema_name=get_public_schema_name())
                        .values_list("schema_name", flat=True)
                )
            executor.run_migrations(tenants=tenants)
예제 #39
0
 def wrapper(*args, **kwargs):
     if settings.MULTI_TENANT:
         for tenant in get_tenant_model().objects.exclude(schema_name="public"):
             with tenant_context(tenant):
                 f(*args, **kwargs)
     else:
         f(*args, **kwargs)
예제 #40
0
    def setUp(self):
        super(TestMultiTenant, self).setUp()

        now = timezone.now()

        self.init_projects()
        self.tenant1 = connection.tenant
        status_running = ProjectPhase.objects.get(slug='campaign')

        # Create a project for the main tenant
        self.project = ProjectFactory.create(status=ProjectPhase.objects.get(slug='campaign'),
                                             deadline=now - timezone.timedelta(days=5),
                                             amount_asked=0)

        # Create a second tenant
        connection.set_schema_to_public()
        tenant_domain = 'testserver2'
        self.tenant2 = get_tenant_model()(
            domain_url=tenant_domain,
            schema_name='test2',
            client_name='test2')

        self.tenant2.save(verbosity=0)
        connection.set_tenant(self.tenant2)

        self.init_projects()
        self.project2 = ProjectFactory.create(status=ProjectPhase.objects.get(slug='campaign'),
                                              deadline=now - timezone.timedelta(days=5),
                                              amount_asked=0)
예제 #41
0
    def get_context_data(self, **kwargs):
        """
        Get the statistics data for the selected tenant, or for all tenants.
        In the last case, the connection will be switched for each tenant,
        and the data for each tenant will be added to the total.
        """
        form = kwargs.get('form')

        all_tenants = None

        if form and form.is_valid():
            self.selected_start = form.get_start()
            self.selected_stop = form.get_stop()
            tenant = form.cleaned_data.get('tenant', None)

            if tenant:
                connection.set_tenant(tenant)
                statistics = get_accounting_statistics(self.selected_start, self.selected_stop)
                totals = get_dashboard_values(self.selected_start, self.selected_stop)

                header = ' - {}'.format(tenant.name)
            else:
                header = ' - All tenants'
                statistics = mydict()
                totals = mydict()
                all_tenants = {}  # contains data for each tenant when all are selected

                for tenant in get_tenant_model().objects.all():
                    
                    connection.set_tenant(tenant)

                    stats = get_accounting_statistics(self.selected_start, self.selected_stop)
                    tots = get_dashboard_values(self.selected_start, self.selected_stop)

                    statistics += stats
                    totals += tots

                    all_tenants[tenant.name] = {
                        'statistics': stats,
                        'totals': tots,
                        'bank_accounts': get_bank_account_info()
                        }
        else:
            header = ''
            statistics, totals = {}, {}

        context = super(MultiTenantAccountingDashboardView, self).get_context_data(**kwargs)

        context.update({
             'statistics': statistics,
             'all_tenants': all_tenants,  # is None in all cases when not 'all tenants' are selected in the multi admin view
             'data': totals,
             'app_label': 'accounting',
             'title': _('Finance Dashboard') + header,
             'start': self.selected_start,
             'stop': self.selected_stop,
        })

        return context
예제 #42
0
 def setUp(self):
     super(ExportKeysTest, self).setUp()
     for tenant in get_tenant_model().objects.all():
         connection.set_tenant(tenant)
         user = BlueBottleUserFactory.create(
             email='*****@*****.**'
         )
         Token.objects.create(user=user)
예제 #43
0
 def wrapper(*args, **kwargs):
     if settings.MULTI_TENANT:
         for tenant in get_tenant_model().objects.exclude(
                 schema_name="public"):
             with tenant_context(tenant):
                 f(*args, **kwargs)
     else:
         f(*args, **kwargs)
예제 #44
0
def get_current_tenant():
    """ Return current tenant
    Determine based on connection schema_name """
    schema_name = connection.schema_name
    connection.set_schema_to_public()
    tenant = get_tenant_model().objects.get(schema_name=schema_name)
    connection.set_tenant(tenant)
    return tenant
예제 #45
0
    def setUpClass(cls):
        # create a tenant
        tenant_domain = 'tenant.test.com'
        cls.tenant = get_tenant_model()(domain_url=tenant_domain,
                                        schema_name='test')
        cls.tenant.save()

        connection.set_tenant(cls.tenant)
예제 #46
0
def index(request):
    tenant_info = get_tenant_model().objects.values("schema_name",
                                                    "domain_url")

    return HttpResponse(u"Main website. <br>"
                        u"User: {user.username}. <br>"
                        u"Tenants: {tenants}. <br>".format(
                            user=request.user, tenants=tenant_info))
예제 #47
0
def get_current_tenant():
    """ Return current tenant
    Determine based on connection schema_name """
    schema_name = connection.schema_name
    connection.set_schema_to_public()
    tenant = get_tenant_model().objects.get(schema_name=schema_name)
    connection.set_tenant(tenant)
    return tenant
예제 #48
0
def show_entry(context, data, panel_class='info'):
    return {
        'user': context.request.user,
        'entrada': data["self"],
        'data': data["information"],
        'panel_class': panel_class,
        'tenant': get_tenant_model()
    }
    def handle(self, *args, **options):
        """
        Iterates a command over all registered schemata.
        """
        if options['schema_name']:
            # only run on a particular schema
            connection.set_schema_to_public()
            self.execute_command(get_tenant_model().objects.get(schema_name=options['schema_name']), self.COMMAND_NAME, *args, **options)
        else:
            # migration needs to be executed first on the public schema, else it might fail to select the tenants
            # if there's a modification on the tenant's table.
            public_schema_name = get_public_schema_name()
            public_tenant = TenantMixin(schema_name=public_schema_name)
            self.execute_command(public_tenant, self.COMMAND_NAME, *args, **options)

            for tenant in get_tenant_model().objects.all():
                if tenant.schema_name != public_schema_name:
                    self.execute_command(tenant, self.COMMAND_NAME, *args, **options)
예제 #50
0
    def handle(self, *args, **options):
        columns = ('schema_name', 'domain_url')

        TenantModel = get_tenant_model()
        all_tenants = TenantModel.objects.values_list(*columns)

        out = csv.writer(sys.stdout, dialect=csv.excel_tab)
        for tenant in all_tenants:
            out.writerow(tenant)
    def handle(self, *args, **options):

        model = get_tenant_model()
        all_tenants = [(t.schema_name, ', '.join(t.get_domains()))
                       for t in model.objects.all()]

        out = csv.writer(sys.stdout, dialect=csv.excel_tab)
        for tenant in all_tenants:
            out.writerow(tenant)
예제 #52
0
    def handle(self, *args, **options):

        model = get_tenant_model()
        all_tenants = [(t.schema_name, ', '.join(t.get_domains()))
                       for t
                       in model.objects.all()]

        out = csv.writer(sys.stdout, dialect=csv.excel_tab)
        for tenant in all_tenants:
            out.writerow(tenant)
 def test_public_schema_on_extra_search_paths(self):
     TenantModel = get_tenant_model()
     TenantModel.objects.create(
         schema_name='demo1', domain_url='demo1.example.com')
     TenantModel.objects.create(
         schema_name='demo2', domain_url='demo2.example.com')
     self.assertBestPractice([
         Critical("public can not be included on PG_EXTRA_SEARCH_PATHS."),
         Critical("Do not include tenant schemas (demo1, demo2) on PG_EXTRA_SEARCH_PATHS."),
     ])
예제 #54
0
    def sync_tenant_apps(self, apps, schema_name=None):
        apps = self.tenant_apps or self.installed_apps
        self._set_managed_apps(apps)
        syncdb_command = SyncdbCommand()
        if schema_name:
            print self.style.NOTICE("=== Running syncdb for schema: %s" % schema_name)
            sync_tenant = get_tenant_model().objects.filter(schema_name=schema_name).get()
            connection.set_tenant(sync_tenant, include_public=False)
            syncdb_command.execute(**self.options)
        else:
            public_schema_name = get_public_schema_name()
            tenant_schemas_count = get_tenant_model().objects.exclude(schema_name=public_schema_name).count()
            if not tenant_schemas_count:
                print self.style.NOTICE("No tenants found")

            for tenant_schema in get_tenant_model().objects.exclude(schema_name=public_schema_name).all():
                print self.style.NOTICE("=== Running syncdb for schema %s" % tenant_schema.schema_name)
                connection.set_tenant(tenant_schema, include_public=False)
                syncdb_command.execute(**self.options)
예제 #55
0
파일: cases.py 프로젝트: sijuaugustin/ingts
    def setUpClass(cls):
        cls.sync_shared()
        tenant_domain = 'tenant.test.com'
        cls.tenant = get_tenant_model()(domain_url=tenant_domain,
                                        schema_name='test')
        cls.tenant.save(
            verbosity=0
        )  # todo: is there any way to get the verbosity from the test command here?

        connection.set_tenant(cls.tenant)
예제 #56
0
    def process_request(self, request):
        super(TenantAwareSessionMiddleware, self).process_request(request)

        # Connection needs first to be at the default schema, as we create session keys using this schema name
        TenantModel = get_tenant_model()
        request.tenant = None
        request.host_tenant = None

        try:
            hostname = request.get_host().split(':')[0]

            sql_query = "SELECT * FROM {tenant_table} WHERE '{hostname}' = ANY(string_to_array(domain_url, ',')) LIMIT 1".format(
                tenant_table=TenantModel._meta.db_table,
                hostname=hostname
            )

            request.host_tenant = TenantModel.objects.raw(sql_query)[0]
        except TenantModel.DoesNotExist:
            pass
        except IndexError:
            pass

        # First check if there is a schema set in the session
        if request.session.get('__schema_name__'):
            try:
                request.tenant = TenantModel.objects.get(schema_name=request.session['__schema_name__'], is_active=True)
            except TenantModel.DoesNotExist:
                raise self.TENANT_NOT_FOUND_EXCEPTION('Invalid tenant stored in session')

        # Fallback to the tenant associated to this host (if any)
        if not request.tenant:
            request.tenant = request.host_tenant

        # If no tenant was set in the request and no tenant could be resolved using the hostname, fallback to the
        # default tenant
        if not request.tenant:
            if settings.DEFAULT_TENANT_SCHEMA == 'public':
                request.tenant = DummyTenant(schema_name='public')
            else:
                request.tenant = TenantModel.objects.get(schema_name=settings.DEFAULT_TENANT_SCHEMA)

        connection.set_tenant(request.tenant)

        # Content type can no longer be cached as public and tenant schemas
        # have different models. If someone wants to change this, the cache
        # needs to be separated between public and shared schemas. If this
        # cache isn't cleared, this can cause permission problems. For example,
        # on public, a particular model has id 14, but on the tenants it has
        # the id 15. if 14 is cached instead of 15, the permissions for the
        # wrong model will be fetched.
        ContentType.objects.clear_cache()

        # Do we have a public-specific urlconf?
        if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
            request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
예제 #57
0
 def handle(self, *args, **options):
     """
     Iterates a command over all registered schemata.
     """
     if options['schema_name']:
         # only run on a particular schema
         self.execute_command(options['schema_name'], self.COMMAND_NAME, *args, **options)
     else:
         for tenant in get_tenant_model().objects.all():
             options['schema_name'] = tenant.schema_name
             self.execute_command(tenant.schema_name, self.COMMAND_NAME, *args, **options)
 def store_tenant(self, **fields):
     try:
         tenant = get_tenant_model().objects.create(**fields)
         tenant.save()
         return True
     except exceptions.ValidationError as e:
         self.stderr.write("Error: %s" % '; '.join(e.messages))
         return False
     except IntegrityError:
         self.stderr.write("Error: Invalid value(s).")
         return False
예제 #59
0
    def dump_tenant_data(self, schema_name=None):
        dumpdb_command = DumpDataCommand()
        if schema_name:
            print self.style.NOTICE("=== Running dumpdata for schema: %s" % schema_name)
            sync_tenant = get_tenant_model().objects.filter(schema_name=schema_name).get()
            connection.set_tenant(sync_tenant, include_public=True)
            dumpdb_command.execute(*self.app_labels, **self.options)
        else:
            public_schema_name = get_public_schema_name()
            tenant_schemas_count = get_tenant_model().objects.exclude(schema_name=public_schema_name).count()
            if not tenant_schemas_count:
                raise CommandError("No tenant schemas found")

            for tenant_schema in get_tenant_model().objects.exclude(schema_name=public_schema_name).all():
                print self.style.NOTICE("=== Running syncdb for schema %s" % tenant_schema.schema_name)
                try:
                    connection.set_tenant(tenant_schema, include_public=True)
                    dumpdb_command.execute(*self.app_labels, **self.options)
                except Exception as e:
                    print e