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'), )
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
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)
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
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)
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
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'))
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)})
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)
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
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
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'))
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
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)
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, )
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 = []