def save(self, verbosity=1, *args, **kwargs): if connection.get_schema() != get_public_schema_name(): raise Exception("Can't update tenant outside the public schema. Current schema is %s." % connection.get_schema()) is_new = self.pk is None super(TenantMixin, self).save(*args, **kwargs) if is_new and self.auto_create_schema: self.create_schema(check_if_exists=True, verbosity=verbosity) post_schema_sync.send(sender=TenantMixin, tenant=self) transaction.commit_unless_managed()
def save(self, verbosity=1, *args, **kwargs): if connection.get_schema() != get_public_schema_name(): raise Exception( "Can't update tenant outside the public schema. Current schema is %s." % connection.get_schema()) is_new = self.pk is None super(TenantMixin, self).save(*args, **kwargs) if is_new and self.auto_create_schema: self.create_schema(check_if_exists=True, verbosity=verbosity) post_schema_sync.send(sender=TenantMixin, tenant=self) transaction.commit_unless_managed()
def delete(self, *args, **kwargs): """ Drops the schema related to the tenant instance. Just drop the schema if the parent class model has the attribute auto_drop_schema set to True. """ if connection.get_schema() not in (self.schema_name, get_public_schema_name()): raise Exception("Can't delete tenant outside it's own schema or the public schema. Current schema is %s." % connection.get_schema()) if schema_exists(self.schema_name) and self.auto_drop_schema: cursor = connection.cursor() cursor.execute('DROP SCHEMA %s CASCADE' % self.schema_name) super(TenantMixin, self).delete(*args, **kwargs)
def save(self, verbosity=1, *args, **kwargs): is_new = self.pk is None if is_new and connection.get_schema() != get_public_schema_name(): raise Exception("Can't create tenant outside the public schema. Current schema is %s." % connection.get_schema()) elif not is_new and connection.get_schema() not in (self.schema_name, get_public_schema_name()): raise Exception("Can't update tenant outside it's own schema or the public schema. Current schema is %s." % connection.get_schema()) if is_new and self.auto_create_schema: self.create_schema(check_if_exists=True, verbosity=verbosity) post_schema_sync.send(sender=TenantMixin, tenant=self) super(TenantMixin, self).save(*args, **kwargs)
def schema_context(schema_name): previous_schema = connection.get_schema() try: connection.set_schema(schema_name) yield finally: connection.set_schema(previous_schema)
def tenant_context(tenant): previous_schema = connection.get_schema() try: connection.set_tenant(tenant) yield finally: connection.set_schema(previous_schema)
def _create_user(self, email, password, is_staff, is_superuser, is_verified, **extra_fields): # Do some schema validation to protect against calling create user from inside # a tenant. Must create public tenant permissions during user creation. This # happens during assign role. This function cannot be used until a public # schema already exists UserModel = get_user_model() if connection.get_schema() != get_public_schema_name(): raise SchemaError( "Schema must be public for UserProfileManager user creation") if not email: raise ValueError("Users must have an email address.") # If no password is submitted, just assign a random one to lock down # the account a little bit. if not password: password = self.make_random_password(length=30) email = self.normalize_email(email) profile = UserModel.objects.filter(email=email).first() if profile and profile.is_active: raise ExistsError("User already exists!") # Profile might exist but not be active. If a profile does exist # all previous history logs will still be associated with the user, # but will not be accessible because the user won't be linked to # any tenants from the user's previous membership. There are two # exceptions to this. 1) The user gets re-invited to a tenant it # previously had access to (this is good thing IMO). 2) The public # schema if they had previous activity associated would be available if not profile: profile = UserModel() profile.email = email profile.is_active = True profile.is_verified = is_verified profile.set_password(password) for attr, value in extra_fields.items(): setattr(profile, attr, value) profile.save() # Get public tenant tenant and link the user (no perms) public_tenant = get_tenant_model().objects.get( schema_name=get_public_schema_name()) public_tenant.add_user(profile) # Public tenant permissions object was created when we assigned a # role to the user above, if we are a staff/superuser we set it here if is_staff or is_superuser: user_tenant = profile.usertenantpermissions user_tenant.is_staff = is_staff user_tenant.is_superuser = is_superuser user_tenant.save() tenant_user_created.send(sender=self.__class__, user=profile) return profile
def inner(self, *args, **options): tenant_schema = self.schema_name # Save current schema and restore it when we're done saved_schema = connection.get_schema() # Set schema to this tenants schema to start building permissions in that tenant connection.set_schema(tenant_schema) try: result = func(self, *args, **options) finally: # Even if an exception is raised we need to reset our schema state connection.set_schema(saved_schema) return result
def _create_user(self, username, email, password, **extra_fields): """ Create and save a user with the given username, email, and password. """ # Do some schema validation to protect against calling create user from inside # a tenant. Must create public tenant permissions during user creation. This # happens during assign role. This function cannot be used until a public # schema already exists UserModel = get_user_model() if connection.get_schema() != get_public_schema_name(): raise SchemaError("Schema must be public for UserManager user creation.") if not username: raise ValueError("The given username must be set.") username = self.model.normalize_username(username) if not email: raise ValueError("Users must have an email address.") email = self.normalize_email(email) # If no password is submitted, just assign a random one to lock down # the account a little bit. if not password: password = self.make_random_password(length=30) user = UserModel.objects.filter(username=username).first() if user and user.is_active: raise ExistsError("User already exists!") # User might exist but not be active. If a user does exist # all previous history logs will still be associated with the user, # but will not be accessible because the user won't be linked to # any tenants from the user's previous membership. There are two # exceptions to this. 1) The user gets re-invited to a tenant it # previously had access to (this is good thing IMO). 2) The public # schema if they had previous activity associated would be available if not user: user = UserModel(username=username, email=email, **extra_fields) user.email = email user.is_active = True user.set_password(password) for attr, value in extra_fields.items(): setattr(user, attr, value) user.save() tenant_user_created.send(sender=self.__class__, user=user) return user
def save(self, verbosity=1, *args, **kwargs): if hasattr(connection, 'get_schema') and connection.get_schema() != get_public_schema_name(): raise Exception("Can't update tenant outside the public schema. Current schema is %s." % connection.get_schema()) is_new = self.pk is None if is_new and settings.TENANT_DYNAMIC_SITE and hasattr(self, 'site_id') and not self.site_id: self.site_id = self.create_site().id print self.site_id super(TenantMixin, self).save(*args, **kwargs) print self.site_id if is_new and self.auto_create_schema and hasattr(connection, 'get_schema'): self.create_schema(check_if_exists=True, verbosity=verbosity) post_schema_sync.send(sender=TenantMixin, tenant=self) transaction.commit_unless_managed()
def get_current_tenant(): current_schema = connection.get_schema() TenantModel = get_tenant_model() tenant = TenantModel.objects.get(schema_name=current_schema) return tenant
def delete(self, *args, **kwargs): if connection.get_schema() not in (self.schema_name, get_public_schema_name()): raise Exception("Can't delete tenant outside it's own schema or the public schema. Current schema is %s." % connection.get_schema()) super(TenantMixin, self).delete(*args, **kwargs)