Esempio n. 1
0
class StructureModel(models.Model):
    """ Generic structure model.
        Provides transparent interaction with base entities and relations like customer.
    """

    objects = StructureManager()

    class Meta:
        abstract = True

    def __getattr__(self, name):
        # add additional properties to the object according to defined Permissions class
        fields = ('customer', 'project')
        if name in fields:
            try:
                path = getattr(self.Permissions, name + '_path')
            except AttributeError:
                pass
            else:
                if not path == 'self' and '__' in path:
                    return reduce(getattr, path.split('__'), self)

        raise AttributeError(
            "'%s' object has no attribute '%s'" % (self._meta.object_name, name)
        )
Esempio n. 2
0
class Project(
        ProjectDetailsMixin,
        core_models.UuidMixin,
        core_models.DescendantMixin,
        core_models.BackendMixin,
        quotas_models.ExtendableQuotaModelMixin,
        PermissionMixin,
        StructureLoggableMixin,
        TimeStampedModel,
        StructureModel,
        SoftDeletableModel,
):
    class Permissions:
        customer_path = 'customer'
        project_path = 'self'

    GLOBAL_COUNT_QUOTA_NAME = 'nc_global_project_count'

    OECD_FOS_2007_CODES = (
        ('1.1', _('Mathematics')),
        ('1.2', _('Computer and information sciences')),
        ('1.3', _('Physical sciences')),
        ('1.4', _('Chemical sciences')),
        ('1.5', _('Earth and related environmental sciences')),
        ('1.6', _('Biological sciences')),
        ('1.7', _('Other natural sciences')),
        ('2.1', _('Civil engineering')),
        (
            '2.2',
            _('Electrical engineering, electronic engineering, information engineering'
              ),
        ),
        ('2.3', _('Mechanical engineering')),
        ('2.4', _('Chemical engineering')),
        ('2.5', _('Materials engineering')),
        ('2.6', _('Medical engineering')),
        ('2.7', _('Environmental engineering')),
        ('2.8', _('Systems engineering')),
        ('2.9', _('Environmental biotechnology')),
        ('2.10', _('Industrial biotechnology')),
        ('2.11', _('Nano technology')),
        ('2.12', _('Other engineering and technologies')),
        ('3.1', _('Basic medicine')),
        ('3.2', _('Clinical medicine')),
        ('3.3', _('Health sciences')),
        ('3.4', _('Health biotechnology')),
        ('3.5', _('Other medical sciences')),
        ('4.1', _('Agriculture, forestry, and fisheries')),
        ('4.2', _('Animal and dairy science')),
        ('4.3', _('Veterinary science')),
        ('4.4', _('Agricultural biotechnology')),
        ('4.5', _('Other agricultural sciences')),
        ('5.1', _('Psychology')),
        ('5.2', _('Economics and business')),
        ('5.3', _('Educational sciences')),
        ('5.4', _('Sociology')),
        ('5.5', _('Law')),
        ('5.6', _('Political science')),
        ('5.7', _('Social and economic geography')),
        ('5.8', _('Media and communications')),
        ('5.9', _('Other social sciences')),
        ('6.1', _('History and archaeology')),
        ('6.2', _('Languages and literature')),
        ('6.3', _('Philosophy, ethics and religion')),
        ('6.4', _('Arts (arts, history of arts, performing arts, music)')),
        ('6.5', _('Other humanities')),
    )

    class Quotas(quotas_models.QuotaModelMixin.Quotas):
        enable_fields_caching = False
        nc_resource_count = quotas_fields.CounterQuotaField(
            target_models=lambda: BaseResource.get_all_models(),
            path_to_scope='project',
        )

    customer = models.ForeignKey(
        Customer,
        verbose_name=_('organization'),
        related_name='projects',
        on_delete=models.PROTECT,
    )
    tracker = FieldTracker()
    type = models.ForeignKey(
        ProjectType,
        verbose_name=_('project type'),
        blank=True,
        null=True,
        on_delete=models.PROTECT,
    )
    oecd_fos_2007_code = models.CharField(choices=OECD_FOS_2007_CODES,
                                          null=True,
                                          blank=True,
                                          max_length=80)

    objects = SoftDeletableManager()
    structure_objects = StructureManager()

    @property
    def is_expired(self):
        return self.end_date and self.end_date <= timezone.datetime.today(
        ).date()

    @property
    def full_name(self):
        return self.name

    def get_users(self, role=None):
        query = Q(
            projectpermission__project=self,
            projectpermission__is_active=True,
        )
        if role:
            query = query & Q(projectpermission__role=role)

        return get_user_model().objects.filter(query).order_by('username')

    @transaction.atomic()
    def _soft_delete(self, using=None):
        """ Method for project soft delete. It doesn't delete a project, only mark as 'removed', but it sends signals
        """
        signals.pre_delete.send(sender=self.__class__,
                                instance=self,
                                using=using)

        self.is_removed = True
        self.save(using=using)

        signals.post_delete.send(sender=self.__class__,
                                 instance=self,
                                 using=using)

    def delete(self, using=None, soft=True, *args, **kwargs):
        """Use soft delete, i.e. mark a project as 'removed'."""
        if soft:
            self._soft_delete(using)
        else:
            return super(SoftDeletableModel, self).delete(using=using,
                                                          *args,
                                                          **kwargs)

    def __str__(self):
        return '%(name)s | %(customer)s' % {
            'name': self.name,
            'customer': self.customer.name,
        }

    def can_user_update_quotas(self, user):
        return user.is_staff or self.customer.has_user(user,
                                                       CustomerRole.OWNER)

    def can_manage_role(self, user, role=None, timestamp=False):
        if user.is_staff:
            return True
        if self.customer.has_user(user, CustomerRole.OWNER, timestamp):
            return True

        return role == ProjectRole.ADMINISTRATOR and self.has_user(
            user, ProjectRole.MANAGER, timestamp)

    def get_log_fields(self):
        return ('uuid', 'customer', 'name')

    def get_parents(self):
        return [self.customer]

    class Meta:
        base_manager_name = 'objects'
Esempio n. 3
0
class Project(
        core_models.DescribableMixin,
        core_models.UuidMixin,
        core_models.NameMixin,
        core_models.DescendantMixin,
        quotas_models.ExtendableQuotaModelMixin,
        PermissionMixin,
        StructureLoggableMixin,
        TimeStampedModel,
        StructureModel,
        SoftDeletableModel,
):
    class Permissions:
        customer_path = 'customer'
        project_path = 'self'

    GLOBAL_COUNT_QUOTA_NAME = 'nc_global_project_count'

    class Quotas(quotas_models.QuotaModelMixin.Quotas):
        enable_fields_caching = False
        nc_resource_count = quotas_fields.CounterQuotaField(
            target_models=lambda: ResourceMixin.get_all_models(),
            path_to_scope='project',
        )
        nc_app_count = quotas_fields.CounterQuotaField(
            target_models=lambda: ApplicationMixin.get_all_models(),
            path_to_scope='project',
        )
        nc_vm_count = quotas_fields.CounterQuotaField(
            target_models=lambda: VirtualMachine.get_all_models(),
            path_to_scope='project',
        )
        nc_private_cloud_count = quotas_fields.CounterQuotaField(
            target_models=lambda: PrivateCloud.get_all_models(),
            path_to_scope='project',
        )
        nc_storage_count = quotas_fields.CounterQuotaField(
            target_models=lambda: Storage.get_all_models(),
            path_to_scope='project',
        )
        nc_volume_count = quotas_fields.CounterQuotaField(
            target_models=lambda: Volume.get_all_models(),
            path_to_scope='project',
        )
        nc_snapshot_count = quotas_fields.CounterQuotaField(
            target_models=lambda: Snapshot.get_all_models(),
            path_to_scope='project',
        )
        nc_volume_size = quotas_fields.TotalQuotaField(
            target_models=lambda: Volume.get_all_models(),
            path_to_scope='project',
            target_field='size',
        )
        nc_snapshot_size = quotas_fields.TotalQuotaField(
            target_models=lambda: Snapshot.get_all_models(),
            path_to_scope='project',
            target_field='size',
        )

    certifications = models.ManyToManyField(to='ServiceCertification',
                                            related_name='projects',
                                            blank=True)
    customer = models.ForeignKey(
        Customer,
        verbose_name=_('organization'),
        related_name='projects',
        on_delete=models.PROTECT,
    )
    tracker = FieldTracker()
    type = models.ForeignKey(
        ProjectType,
        verbose_name=_('project type'),
        blank=True,
        null=True,
        on_delete=models.PROTECT,
    )

    objects = SoftDeletableManager()
    structure_objects = StructureManager()

    @property
    def full_name(self):
        return self.name

    def get_users(self, role=None):
        query = Q(
            projectpermission__project=self,
            projectpermission__is_active=True,
        )
        if role:
            query = query & Q(projectpermission__role=role)

        return get_user_model().objects.filter(query).order_by('username')

    @transaction.atomic()
    def _soft_delete(self, using=None):
        """ Method for project soft delete. It doesn't delete a project, only mark as 'removed',
        but it sends needed signals and delete ServiceProjectLink objects
        """
        signals.pre_delete.send(sender=self.__class__,
                                instance=self,
                                using=using)

        for model in ServiceProjectLink.get_all_models():
            for spl in model.objects.filter(project=self):
                spl.delete()

        self.is_removed = True
        self.save(using=using)

        signals.post_delete.send(sender=self.__class__,
                                 instance=self,
                                 using=using)

    def delete(self, using=None, soft=True, *args, **kwargs):
        """Use soft delete, i.e. mark a project as 'removed'."""
        if soft:
            self._soft_delete(using)
        else:
            return super(SoftDeletableModel, self).delete(using=using,
                                                          *args,
                                                          **kwargs)

    def __str__(self):
        return '%(name)s | %(customer)s' % {
            'name': self.name,
            'customer': self.customer.name,
        }

    def can_user_update_quotas(self, user):
        return user.is_staff or self.customer.has_user(user,
                                                       CustomerRole.OWNER)

    def can_manage_role(self, user, role, timestamp=False):
        """
        Checks whether user can grant/update/revoke project permissions for specific role.
        `timestamp` can have following values:
            - False - check whether user can manage permissions at the moment.
            - None - check whether user can permanently manage permissions.
            - Datetime object - check whether user will be able to manage permissions at specific timestamp.
        """
        if user.is_staff:
            return True
        if self.customer.has_user(user, CustomerRole.OWNER, timestamp):
            return True

        return role == ProjectRole.ADMINISTRATOR and self.has_user(
            user, ProjectRole.MANAGER, timestamp)

    def get_log_fields(self):
        return ('uuid', 'customer', 'name')

    def get_parents(self):
        return [self.customer]

    def get_children(self):
        """
        Get all service project links connected to current project
        """
        return itertools.chain.from_iterable(
            m.objects.filter(project=self)
            for m in ServiceProjectLink.get_all_models())

    class Meta:
        base_manager_name = 'objects'