Example #1
0
 def get_queryset(self):
     client = self.request.user.clients.filter(
         services__openstack_project__isnull=False).first()
     if not client:
         raise APIConflict(_('No client with an OpenStack project found'))
     return Network.objects.get_networks_for_project(
         project_id=client.first_project.project_id,
         external=active_features.is_enabled(
             'openstack.networks.display_external_networks'),
         shared=active_features.is_enabled(
             'openstack.networks.display_shared_networks'),
     )
Example #2
0
def check_sfa_required_and_get_settings(
        user: AppUser) -> (bool, Optional[Response]):
    if user.is_staff:
        if not staff_active_features.is_enabled(
                'clients&users.second_factor_auth'):
            return False, None
    else:
        if not active_features.is_enabled('clients&users.second_factor_auth'):
            return False, None
    sfa_methods = SecondFactorAuthMethod.objects.filter(user=user,
                                                        enabled=True)
    enabled_sfa_methods = sfa_methods.count()
    if enabled_sfa_methods:
        # if user has sfa methods enabled, sfa is required and he'll be able to choose from one of those
        available_sfa_methods = list()
        for method in sfa_methods:
            available_sfa_methods.append(
                dict(
                    name=method.type.name,
                    display_name=method.type.display_name,
                    default=method.default,
                    help_text=method.type.help_text,
                ))
        return True, Response({
            'detail':
            _('Second factor authentication required'),
            'sfa_required':
            True,
            'sfa_methods':
            available_sfa_methods,
        })
    return False, None
Example #3
0
def billing_summary_view(request):
    client = request.user.clients.first()
    client_operations = ClientOperations(client=client)
    unpaid_usage = client_operations.client_usage.unpaid_usage
    uptodate_credit = client_operations.uptodate_credit
    other_credit = client.credits.exclude(currency=client.currency)
    services = ServiceBriefSerializer(many=True).to_representation(
        Service.objects.available_to_user(request.user))
    summary = {
        'credits': ClientCreditMinSerializer(instance=other_credit,
                                             many=True).data,
        'uptodate_credit': uptodate_credit,
        'billing_currency': client.currency.code,
        'unpaid_usage': unpaid_usage,
        'services': services,
    }

    if active_features.is_enabled('billing.invoices'):
        invoices_count = Invoice.objects.filter(client=client).count()
        unpaid_invoices_count = Invoice.objects.filter(
            client=client, status=InvoiceStatus.ST_UNPAID).count()
        paid_invoices_count = Invoice.objects.filter(
            client=client, status=InvoiceStatus.ST_PAID).count()
        summary['invoices_details'] = dict(
            invoices_count=invoices_count,
            unpaid_invoices_count=unpaid_invoices_count,
            paid_invoices_count=paid_invoices_count,
        )

    return Response(summary)
Example #4
0
    def refresh_plugins(self):
        definitions = {}  # type: Dict[str, PluginDefinition]
        for app_config in apps.apps.get_app_configs():  # type: apps.AppConfig
            if hasattr(app_config, 'initialize_plugin') and callable(
                    app_config.initialize_plugin):
                LOG.info('Found plugin {}'.format(app_config.name))
                definition = app_config.initialize_plugin(
                )  # type: PluginDefinition
                definition.refresh_components()
                definitions[definition.app_label] = definition

        self.found_plugin_definitions = dict(definitions)

        plugins_in_db = []

        # update database
        for plugin in Plugin.objects.all():
            if plugin.app_label in definitions:
                plugins_in_db.append(plugin.app_label)

                if not plugin.app_loaded:
                    plugin.app_loaded = True
                    plugin.save(update_fields=['app_loaded'])

                # remove disabled definitions
                if not plugin.enabled:
                    del definitions[plugin.app_label]
                else:
                    definitions[plugin.app_label].plugin_model = plugin
            else:
                if plugin.app_loaded:
                    plugin.app_loaded = False
                    plugin.save(update_fields=['app_loaded'])

        for app_label in definitions:
            if app_label not in plugins_in_db:
                plugin_definition = definitions[
                    app_label]  # type: PluginDefinition
                plugin_definition.plugin_model = Plugin.objects.create(
                    display_name=plugin_definition.display_name,
                    app_name=plugin_definition.app_name,
                    app_label=plugin_definition.app_label,
                    feature_name=plugin_definition.feature_name,
                    staff_feature_name=plugin_definition.staff_feature_name,
                    app_loaded=True)

        for definition in definitions.values():
            if active_features.is_enabled(definition.feature_name):
                LOG.info('Plugin {} is enabled for enduser'.format(
                    definition.app_label))
                self.enduser_active_plugin_definitions[
                    definition.app_label] = definition
            if staff_active_features.is_enabled(definition.staff_feature_name):
                LOG.info('Plugin {} is enabled for staff'.format(
                    definition.app_label))
                self.staff_active_plugin_definitions[
                    definition.app_label] = definition

        self.active_plugin_definitions = definitions
Example #5
0
def add_log(category, logclass_name, logclass_type, user=None, ip=None, **kwargs):
    log_class = _fetch_log_class(category, logclass_name, logclass_type)

    if active_features.is_enabled('demo'):
        # do not record visitors IP in demo mode
        ip = None

    Log.objects.create(user=user, ip=ip, log_class=log_class, parameters=kwargs)
Example #6
0
 def validate(self, attrs):
     attrs = super(ImageCreateSerializer, self).validate(attrs)
     if attrs.get('source') == 'file' and not active_features.is_enabled(
             'openstack.images.file_uploads'):
         raise serializers.ValidationError(
             detail={'source': 'File uploads are not allowed.'})
     if attrs.get('source') == 'file' and not attrs.get('file'):
         raise serializers.ValidationError(
             detail={'source': 'A File is required'})
     elif attrs.get('source') == 'url' and not attrs.get('url'):
         raise serializers.ValidationError(
             detail={'url': 'A valid URL is required'})
     return attrs
Example #7
0
 def perform_update(self, serializer):
     db_image = serializer.instance
     if not active_features.is_enabled('openstack.images.updatecreate'):
         raise ForbiddenException(_('Image editing not allowed'))
     try:
         self.os_api.images.update(image=db_image,
                                   **serializer.validated_data)
     except GlanceForbiddenException as e:
         LOG.exception(e)
         handle(self.request, message=_('Image update forbidden'))
     except Exception as e:
         LOG.exception(e)
         handle(self.request, message=_('Image update failed'))
Example #8
0
    def reactivate(self, request, pk):
        del request, pk  # unused

        image = self.get_object()
        if not active_features.is_enabled('openstack.images.updatecreate'):
            raise ForbiddenException(_('Image reactivation not allowed'))
        try:
            self.os_api.images.reactivate(image=image)
        except (Exception, GlanceNotFoundException) as e:
            if type(e) == GlanceNotFoundException:
                raise ObjectNotFound(detail=e.details)
            LOG.exception(e)
            handle(self.request)
        return Response({'detail': _('Image {} reactivated').format(image)})
Example #9
0
    def handle(self, *args, **options):
        if options['type'] == 'staff':
            sys.exit(0 if staff_active_features.is_enabled(options['feature']
                                                           ) else 1)

        if options['type'] == 'reseller':
            sys.exit(0 if reseller_active_features.
                     is_enabled(options['feature']) else 1)

        if options['type'] == 'enduser':
            sys.exit(
                0 if active_features.is_enabled(options['feature']) else 1)

        sys.exit(1)
Example #10
0
 def get_queryset(self):
     filter_params = Q(
         project__service__client__in=self.request.user.clients.all())
     try:
         project_id = self.request.user.clients.first(
         ).first_project.project_id
     except Exception:
         raise APIConflict(_('No client with an OpenStack project found'))
     else:
         if active_features.is_enabled('openstack.images.showshared'):
             filter_params = filter_params | Q(
                 visibility=OpenStackImageVisibility.SHARED,
                 members__member_id=project_id,
                 members__status__in=(ImageMemberStatus.ACCEPTED,
                                      ImageMemberStatus.PENDING))
     queryset = Image.objects.filter(filter_params).exclude(
         status='deleted')
     return queryset
Example #11
0
    def resize_flavors(self, staff_request=False):
        """
        Return a queryset containing the flavors allowed for resize.
        Filter by client groups if the instance has a project associated
        with a Fleio client.
        :rtype: django.db.models.query.Queryset
        """
        project_id = self.instance.project_id
        show_in_fleio = True
        if staff_request:
            show_in_fleio = None
        try:
            instance_related_image = self.instance.image
        except Image.DoesNotExist:
            instance_related_image = None
        if project_id:
            qs = OpenstackInstanceFlavor.objects.get_for_project(
                project_id=project_id,
                disabled=False,
                region=self.instance.region,
                deleted=False,
                is_public=True,
                show_in_fleio=show_in_fleio).order_by('memory_mb')
        else:
            qs = OpenstackInstanceFlavor.objects.filter(
                disabled=False,
                region=self.instance.region,
                deleted=False,
                is_public=True,
                show_in_fleio=show_in_fleio).order_by('memory_mb')
        if instance_related_image:
            if instance_related_image.flavors.count(
            ) + instance_related_image.flavor_groups.count() > 0:
                qs = qs.filter(
                    Q(images__id=instance_related_image.id)
                    | Q(flavor_group__images__id=instance_related_image.id))

        if not staff_request and not active_features.is_enabled(
                'openstack.instances.resize.allow_resize_to_less_disk_space'):
            qs = qs.filter(root_gb__gte=self.instance.flavor.root_gb)

        return qs
Example #12
0
def confirm_login(user, remember=False, **args) -> Optional[str]:
    """Method called when user supplies second factor authentication info on login
    Returns either the remember token or None, in either case the user will get logged in
    Raising exception denies access to user"""
    if user.is_staff:
        demo_mode = staff_active_features.is_enabled('demo')
    else:
        demo_mode = active_features.is_enabled('demo')
    if demo_mode:
        return None  # in demo mode, allow any input and sign in the user

    code = args.get('code')
    if not code:
        raise APIBadRequest(_('Confirmation code is missing'))
    try:
        int(code)
    except Exception as e:
        del e  # unused
        raise APIBadRequest(_('Code has to be a number'))
    if int(code) > 999999:
        raise APIBadRequest(_('Code has to be a 6 digit number'))
    sfa_type = SecondFactorAuthType.objects.filter(name=utils_get_app_name(
        app_name=SMSAuthenticatorPluginConfig.name)).first()
    if not sfa_type:
        raise SFATypeNotFound()
    sfa_method = SecondFactorAuthMethod.objects.filter(user=user,
                                                       type=sfa_type).first()
    if not sfa_method:
        raise SFAMethodNotAdded()
    sms_auth_data = SMSAuthenticatorData.objects.filter(
        method=sfa_method).first()
    secret_key = sms_auth_data.get_secret_key()
    result = pyotp.hotp.HOTP(secret_key).verify(otp=code,
                                                counter=sms_auth_data.counter)
    if result:
        sms_auth_data.counter = sms_auth_data.counter + 1
        sms_auth_data.save(update_fields=['counter'])
        if remember:
            return RememberSfa(user=user).make_token()
        return None
    else:
        raise APIBadRequest(_('Code is invalid'))
Example #13
0
    def download(self, request, pk):
        del pk, request  # unused

        if not active_features.is_enabled('openstack.images.download'):
            raise ForbiddenException(_('Image download not allowed'))

        db_image = self.get_object()  # type: Image
        try:
            image_data = self.os_api.images.download(image=db_image)
        except (Exception, GlanceNotFoundException) as e:
            if type(e) == GlanceNotFoundException:
                raise ObjectNotFound(detail=e.details)
            LOG.exception(e)
            handle(self.request)
        else:
            response = StreamingHttpResponse(streaming_content=image_data)
            response['Content-Type'] = 'application/octet-stream'
            response[
                'Content-Disposition'] = 'attachment; filename="{}"'.format(
                    db_image.name)
            return response
Example #14
0
 def create(self, request, *args, **kwargs):
     serializer = self.get_serializer(data=request.data)
     serializer.is_valid(raise_exception=True)
     if not validate_cloud_objects_limit():
         raise APIBadRequest(
             _('Licence cloud objects limit reached. Please check your license.'
               ))
     if not active_features.is_enabled('openstack.images.updatecreate'):
         raise ForbiddenException(_('Image creation not allowed'))
     try:
         image = self.os_api.images.create(owner=self.os_api.project,
                                           **serializer.validated_data)
     except Exception as e:
         LOG.error(e)
         handle(self.request, message='Unable to create the image')
     else:
         headers = self.get_success_headers(serializer.data)
         data = serializer.data
         data['id'] = image.id
         return Response(data,
                         status=status.HTTP_201_CREATED,
                         headers=headers)
Example #15
0
    def start_view_activity(self,
                            activity_category: LogCategory,
                            activity_class: str,
                            request: Request,
                            object_id=None):
        # do not record visitors IP in demo mode
        ip = None if active_features.is_enabled('demo') else get_ip(request)
        user = request.user
        if not isinstance(user, AppUser):
            user = None

        parameters = {}

        if user:
            parameters['username'] = user.username
            parameters['user_id'] = user.id

        impersonator = getattr(request, 'impersonator', None)
        if impersonator:
            parameters['impersonator'] = impersonator.username
            parameters['impersonator_id'] = impersonator.id

        if object_id is not None:
            parameters['object_id'] = object_id

        info_log_class, _ = LogClass.objects.get_or_create(
            category=activity_category,
            name=activity_class,
            type='info',
        )

        self.thread_local.current_activity = Log.objects.create(
            user=user,
            ip=ip,
            log_class=info_log_class,
            parameters=parameters,
        )
Example #16
0
                    EndUserClusterViewSet,
                    basename='clusters',
                    feature_name='openstack.coe.clusters')

    try:
        from fleio.osbilling.views import ServiceDynamicUsageViewset, ServiceDynamicUsageHistoryViewset
        router.register(r'billing/history',
                        ServiceDynamicUsageHistoryViewset,
                        basename='billing-history',
                        feature_name='billing.history')
        router.register(r'billing',
                        ServiceDynamicUsageViewset,
                        basename='billing',
                        feature_name='billing.history')
    except ImportError as e:
        pass

    if not active_features.is_enabled('openstack.instances.snapshots'):
        # TODO(tomo): Fix this handling of snapshots as a feature
        snapshot_url_list = list(
            filter(lambda link: link.name == u'instances-create-snapshot',
                   router.urls))
        if snapshot_url_list:
            del router.urls[router.urls.index(snapshot_url_list[0])]

    urlpatterns = [
        url(r'^openstack/', include(router.urls)),
    ]
except ImportError:
    urlpatterns = []