Ejemplo n.º 1
0
 def is_manageable_by_reseller(user, db_image: Image, message):
     reseller_resources = user_reseller_resources(user=user)
     manageable = False
     try:
         if db_image.reseller_resources == reseller_resources:
             manageable = True
         if (not manageable and db_image.project.service
                 and (db_image.project.service.client.reseller_resources
                      and db_image.project.service.client.reseller_resources
                      == reseller_resources)):
             manageable = True
         if (not manageable and 'image_type' in db_image.properties
                 and db_image.properties['image_type'] == 'snapshot'):
             # if snapshot, first check if related instance is related to the reseller resources
             if 'instance_uuid' in db_image.properties:
                 related_instance = Instance.objects.filter(
                     id=db_image.properties['instance_uuid']).first()
                 if related_instance:
                     if related_instance.project.service.client.reseller_resources == reseller_resources:
                         manageable = True
     except Exception:
         raise ForbiddenException(
             _('Could not determine if image is related to reseller service.'
               ))
     if not manageable:
         raise ForbiddenException(message)
Ejemplo n.º 2
0
    def dissociate_user(self, request, pk):
        del pk  # unused
        if reseller_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        client = self.get_object()
        try:
            # delete the cart related to client
            client_cart = client.fleio_cart
            client_cart.delete()
        except Client.fleio_cart.RelatedObjectDoesNotExist:
            pass
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user_model = get_user_model()
        try:
            user = user_model.objects.get(
                id=serializer.validated_data['user_id'])
            try:
                # delete the cart related to user
                user_cart = user.fleio_cart
                user_cart.delete()
            except user_model.fleio_cart.RelatedObjectDoesNotExist:
                pass
        except user_model.DoesNotExist:
            raise ObjectNotFound({'detail': _('User not found')})
        UserToClient.objects.filter(user=user, client=client).delete()
        return Response({'detail': _('User dissociated')})
Ejemplo n.º 3
0
    def destroy(self, request, pk=None):
        """Delete an OpenStack user"""

        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        try:
            project_ids = [
                project.project_id for project in self.projects_queryset()
            ]

            os_user = self.os_user_api.get_user(user=pk)
            if getattr(os_user, 'default_project_id', None) not in project_ids:
                LOG.error(
                    'Could not delete user with id {pk}, because project {project} not found in database.'
                    .format(pk=pk, project=os_user.default_project_id))
                raise ValidationError({
                    'detail':
                    _('Unable to delete the user from OpenStack. Check logs for more info'
                      )
                })

            self.os_user_api.delete_user(user=pk)
        except (ClientException, IndexError) as e:
            LOG.error('Could not delete user with id {pk}, reason: {0}'.format(
                e, pk=pk))
            raise ValidationError({
                'detail':
                _('Unable to delete the user from OpenStack. Check logs for more info'
                  )
            })
        else:
            return Response({'detail': _('User deleted')},
                            status=HTTP_204_NO_CONTENT)
Ejemplo n.º 4
0
 def token(self, request, pk):
     del request, pk  # unused
     user = self.get_object()
     if not user.is_active:
         raise ForbiddenException(detail=_('User account is inactive'))
     token, created = Token.objects.get_or_create(user=user)
     return Response({'token': token.key})
Ejemplo n.º 5
0
 def perform_destroy(self, instance: AppUser):
     if (instance.is_superuser or instance.username
             == 'demo') and staff_active_features.is_enabled('demo'):
         # don't allow deletion of superuser or enduser demo account in demo mode
         raise ForbiddenException(
             detail=_('Operation not allowed in demo mode'))
     if instance.is_superuser:
         if self.request.user.username == instance.username or self.request.user.is_superuser is False:
             raise PermissionDenied
     pk = instance.id
     if instance.username == self.request.user.username:
         raise APIBadRequest(
             _('Cannot delete the user you are logged in with.'))
     with transaction.atomic():
         if instance.permissions:
             instance.permissions.delete()
         instance.delete()
         user = self.request.user
         staff_delete_user.send(sender=__name__,
                                user=user,
                                user_id=user.id,
                                deleted_user_name=instance.username,
                                deleted_user_id=pk,
                                username=user.username,
                                request=self.request)
Ejemplo n.º 6
0
    def create_reseller_service(self, request, pk):
        del pk  # unused

        # TODO - #1019: implement proper creation of service here
        serializer = StaffCreateServiceSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        client = self.get_object()
        reseller_resources = client_reseller_resources(client=client)

        if reseller_resources is not None:
            raise ForbiddenException(
                {'detail': _('Client already has a reseller service')})

        reseller_product = Product.objects.get(
            id=serializer.validated_data['product_id'])
        reseller_product_cycle = reseller_product.cycles.filter(
            id=serializer.validated_data['product_cycle_id'])[0]

        service = Service.objects.create(
            client=client,
            product=reseller_product,
            cycle=reseller_product_cycle,
            display_name='Reseller service',
            status=ServiceStatus.active,
        )

        module_factory.get_module_instance(service=service).create(
            service=service)

        return Response({'detail': _('Ok')})
Ejemplo n.º 7
0
 def perform_create(self, serializer):
     serializer.is_valid(raise_exception=True)
     new_user_is_superuser = serializer.validated_data.get('is_superuser')
     if new_user_is_superuser and staff_active_features.is_enabled('demo'):
         # don't allow creation of superusers in demo mode
         raise ForbiddenException(
             detail=_('Operation not allowed in demo mode'))
     # Don't allow users to create super users
     if new_user_is_superuser is True and self.request.user.is_superuser is False:
         raise PermissionDenied
     serializer.save()
Ejemplo n.º 8
0
    def update_frontend(self, request, *args, **kwargs):
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        del request, args, kwargs  # unused

        try:
            index_manager = IndexManager()
            index_manager.update_frontend()
        except IndexManager.IndexUpdateException as e:
            raise APIBadRequest(detail=e.detail)

        return Response()
Ejemplo n.º 9
0
    def perform_destroy(self, db_image):
        """Delete the image."""
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(detail=_('Operation not allowed in demo mode'))

        img = self.get_image()
        if img.db_image.protected:
            raise APIConflict(_("Can't delete protected image"))
        try:
            img.delete()
            user = self.request.user
            staff_delete_image.send(sender=__name__, user=user, user_id=user.id,
                                    image_name=img.db_image.name, image_id=img.db_image.id,
                                    username=user.username, request=self.request)
        except Exception as e:
            LOG.error("Cannot delete image, reason: {}".format(repr(e)))
            handle(self.request)
Ejemplo n.º 10
0
    def delete_project(self, request, pk):
        del pk  # unused

        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        delete_all_resources = request.data.get('delete_all_resources', False)
        instance = self.get_object()
        if delete_all_resources:
            tasks.delete_client_project_resources.delay(
                project_id=instance.project_id, mark_project_as_deleted=False)
            return Response(status=200,
                            data={'details': _('Project delete scheduled')})
        else:
            project = OpenstackProject.with_admin_session(instance.project_id)
            project.delete()
            return Response(status=200, data={'details': _('Project deleted')})
Ejemplo n.º 11
0
 def perform_destroy(self, instance):
     if instance.is_default:
         raise ForbiddenException(
             {'detail': 'Cannot delete the default currency'})
     try:
         instance.delete()
     except ProtectedError as e:
         raise APIBadRequest(
             detail={
                 'error_type':
                 'ProtectedError',
                 'detail':
                 e,
                 'user_friendly_message':
                 _('Currency cannot be deleted because it is used by other objects'
                   )
             })
     except IntegrityError as e:
         raise APIBadRequest(detail=e.args[1])
Ejemplo n.º 12
0
    def download(self, request, pk):
        del pk, request  # unused

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

        db_image = self.get_object()  # type: OpenstackImage
        try:
            images_api = Images(api_session=self.os_admin_api.session)
            image_data = images_api.download(image=db_image)
        except (Exception, HTTPNotFound) as e:
            if type(e) == HTTPNotFound:
                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
Ejemplo n.º 13
0
    def save_custom_code(self, request, *args, **kwargs):
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        del args, kwargs  # unused

        custom_code = request.data.get('custom_code', None)
        if custom_code:
            for insertion_point in custom_code:
                custom_code_id = custom_code[insertion_point]['data'].get(
                    'id', None)
                instance = CustomCode.objects.filter(
                    id=custom_code_id).first() if custom_code_id else None
                serializer = CustomCodeSerializer(
                    data=custom_code[insertion_point]['data'],
                    instance=instance)
                if serializer.is_valid(raise_exception=True):
                    serializer.save()

        return Response()
Ejemplo n.º 14
0
    def perform_destroy(self, db_flavor):
        """Delete flavor from nova and mark as deleted in Fleio db."""
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        flavor_api = Flavors(api_session=self.identity_admin_api.session)
        flavor = flavor_api.get(flavor=db_flavor)
        try:
            pk = db_flavor.id
            flavor.delete()
            user = self.request.user
            staff_delete_flavor.send(sender=__name__,
                                     user=user,
                                     user_id=user.id,
                                     flavor_name=db_flavor.name,
                                     flavor_id=pk,
                                     username=user.username,
                                     request=self.request)
        except Exception as e:
            LOG.error(e)
            handle(self.request, message=e)
Ejemplo n.º 15
0
    def update_frontend(self):
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        if not self.is_local_frontend():
            raise IndexManager.IndexUpdateException(
                detail=_('Cannot find frontend instalation'))

        self.update_vanilla_indexes()

        if not self.has_vanilla_indexes():
            raise IndexManager.IndexUpdateException(
                detail=_('No unmodified index.html file available'))

        self.generate_updates_indexes()

        if not self.has_updated_indexes():
            raise IndexManager.IndexUpdateException(
                detail=_('Failed to generate updated index.html file'))

        self.update_local_frontend()
Ejemplo n.º 16
0
 def allowed_to_update(user):
     if user.is_superuser is True and staff_active_features.is_enabled(
             'demo'):
         raise ForbiddenException(
             detail=_('Operation not allowed in demo mode'))
Ejemplo n.º 17
0
    def perform_update(self, serializer):
        if staff_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        user = serializer.instance
        request_user = self.request.user

        updated_user_fields = get_user_changed_values(
            user, serializer.validated_data)
        log_text = format_for_log(updated_user_fields)

        password_changed = False
        if 'password' in serializer.validated_data:
            password_changed = True

        # Don't allow users to edit super user
        if user.is_superuser:
            if request_user.is_superuser is False:
                raise PermissionDenied

        # Change superuser status only if the user who makes the request is also a superuser
        if 'is_superuser' in serializer.validated_data:
            if request_user.is_superuser is False:
                serializer.validated_data.pop('is_superuser', None)
            else:
                # if the instance user gets marked as superuser also mark it as staff
                if serializer.validated_data['is_superuser'] is True:
                    serializer.validated_data['is_staff'] = True

        # Don't allow superuser to remove it's own superuser status
        if request_user == user and request_user.is_superuser is True:
            if 'is_superuser' in serializer.validated_data:
                if serializer.validated_data['is_superuser'] is False:
                    raise APIBadRequest(
                        detail=_('Cannot remove own superuser status'))

        # Don't allow updating a regular user to staff if user has clients
        if serializer.validated_data.get('is_staff',
                                         False) and not user.is_staff:
            if user.clients.count() > 0:
                raise APIBadRequest(detail=_(
                    'Cannot have a staff user with clients associated. Dissociate all clients and try again.'
                ), )

        serializer.save()

        if password_changed and updated_user_fields:
            if request_user == user:
                user_update_password.send(sender=__name__,
                                          user=request_user,
                                          user_id=request_user.pk,
                                          username=request_user.username,
                                          email=request_user.email,
                                          request=self.request)
                user_update.send(sender=__name__,
                                 user=request_user,
                                 username=request_user.username,
                                 user_id=request_user.pk,
                                 email=request_user.email,
                                 request=self.request,
                                 updated_data=log_text)
            else:
                staff_altered_user_password.send(
                    sender=__name__,
                    user=request_user,
                    user_id=request_user.pk,
                    username=request_user.username,
                    username_changed=user.username,
                    user_changed_id=user.pk,
                    request=self.request)
                staff_altered_user_data.send(sender=__name__,
                                             user=request_user,
                                             username=request_user.username,
                                             user_id=request_user.pk,
                                             username_changed=user.username,
                                             user_changed_id=user.pk,
                                             request=self.request,
                                             updated_data=log_text)
        elif password_changed:
            if request_user == user:
                user_update_password.send(sender=__name__,
                                          user=request_user,
                                          username=request_user.username,
                                          user_id=request_user.pk,
                                          email=request_user.email,
                                          request=self.request)
            else:
                staff_altered_user_password.send(
                    sender=__name__,
                    user=request_user,
                    user_id=request_user.pk,
                    username=request_user.username,
                    username_changed=user.username,
                    user_changed_id=user.pk,
                    request=self.request)
        elif updated_user_fields:
            if request_user == user:
                user_update.send(sender=__name__,
                                 user=request_user,
                                 username=request_user.username,
                                 user_id=request_user.pk,
                                 email=request_user.email,
                                 request=self.request,
                                 updated_data=log_text)
            else:
                staff_altered_user_data.send(sender=__name__,
                                             user=request_user,
                                             username=request_user.username,
                                             user_id=request_user.pk,
                                             username_changed=user.username,
                                             user_changed_id=user.pk,
                                             request=self.request,
                                             updated_data=log_text)
Ejemplo n.º 18
0
 def allowed_to_update(user):
     if user.is_superuser is True or user.is_staff is True or not user.is_reseller:
         raise ForbiddenException(detail=_('Cannot update own staff or reseller status.'))
Ejemplo n.º 19
0
    def perform_update(self, serializer):
        if reseller_active_features.is_enabled('demo'):
            raise ForbiddenException(
                detail=_('Operation not allowed in demo mode'))

        user = serializer.instance
        request_user = self.request.user

        updated_user_fields = get_user_changed_values(
            user, serializer.validated_data)
        log_text = format_for_log(updated_user_fields)

        password_changed = False
        if 'password' in serializer.validated_data:
            password_changed = True

        reseller_resources = user_reseller_resources(self.request.user)
        # Do not allow editing of users not assigned to reseller
        if user != self.request.user and user.reseller_resources != reseller_resources:
            raise PermissionDenied

        serializer.save()

        if password_changed and updated_user_fields:
            if request_user == user:
                user_update_password.send(
                    sender=__name__,
                    user=request_user,
                    user_id=request_user.pk,
                    username=request_user.username,
                    email=request_user.email,
                    request=self.request,
                )
                user_update.send(
                    sender=__name__,
                    user=request_user,
                    username=request_user.username,
                    user_id=request_user.pk,
                    email=request_user.email,
                    request=self.request,
                    updated_data=log_text,
                )
            else:
                reseller_altered_user_password.send(
                    sender=__name__,
                    user=request_user,
                    user_id=request_user.pk,
                    username=request_user.username,
                    username_changed=user.username,
                    user_changed_id=user.pk,
                    request=self.request,
                )
                reseller_altered_user_data.send(
                    sender=__name__,
                    user=request_user,
                    username=request_user.username,
                    user_id=request_user.pk,
                    username_changed=user.username,
                    user_changed_id=user.pk,
                    request=self.request,
                    updated_data=log_text,
                )
        elif password_changed:
            if request_user == user:
                user_update_password.send(
                    sender=__name__,
                    user=request_user,
                    username=request_user.username,
                    user_id=request_user.pk,
                    email=request_user.email,
                    request=self.request,
                )
            else:
                reseller_altered_user_password.send(
                    sender=__name__,
                    user=request_user,
                    user_id=request_user.pk,
                    username=request_user.username,
                    username_changed=user.username,
                    user_changed_id=user.pk,
                    request=self.request,
                )
        elif updated_user_fields:
            if request_user == user:
                user_update.send(
                    sender=__name__,
                    user=request_user,
                    username=request_user.username,
                    user_id=request_user.pk,
                    email=request_user.email,
                    request=self.request,
                    updated_data=log_text,
                )
            else:
                reseller_altered_user_data.send(sender=__name__,
                                                user=request_user,
                                                username=request_user.username,
                                                user_id=request_user.pk,
                                                username_changed=user.username,
                                                user_changed_id=user.pk,
                                                request=self.request,
                                                updated_data=log_text)
Ejemplo n.º 20
0
    def create_openstack_service(self, request, pk):
        del pk  # unused

        # TODO - #1019: implement proper creation of service here
        serializer = CreateServiceSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        client = self.get_object()

        if client.first_project is not None and client.first_project.deleted is False:
            raise ForbiddenException(
                {'detail': _('Client already has a project')})

        project_id = serializer.validated_data.get('project_id', 'none')

        if Client.objects.filter(
                services__openstack_project__project_id=project_id):
            raise ForbiddenException(
                {'detail': _('Project already associated with a client')})

        openstack_product = Product.objects.get(
            id=serializer.validated_data['product_id'])
        openstack_product_cycle = openstack_product.cycles.filter(
            id=serializer.validated_data['product_cycle_id'])[0]
        service_external_id = serializer.validated_data.get(
            'service_external_id', None)

        with transaction.atomic():
            if serializer.validated_data['create_new_project']:
                try:
                    ProjectModel.objects.create_project(
                        client=client,
                        openstack_product=openstack_product,
                        openstack_product_cycle=openstack_product_cycle,
                        service_external_id=service_external_id,
                    )
                except Conflict:
                    return Response(
                        status=409,
                        data={
                            'detail':
                            _('A project already exists for this client')
                        })
                except RoleDoesNotExist:
                    # TODO: going to the exact settings page and field isn't implemented yet in frontend
                    # on implementation in frontend change section and configuration_id if necessary
                    # (Issue: https://git.fleio.org/fleio/fleio/issues/1922)
                    if plugin_settings.default_role:
                        error_message = _(
                            'Role "{}" does not exist in OpenStack. Set an existing role as default '
                            'role.').format(plugin_settings.default_role)
                    else:
                        error_message = _(
                            'OpenStack role was not set in OpenStack settings -> defaults tab. '
                            'Set an existing role as default role.')
                    raise ConfigException(message=error_message,
                                          section='openstack_plugin_defaults',
                                          configuration_id='default_role')
            else:
                try:
                    project = IdentityAdminApi(
                        request_session=request.session).client.projects.get(
                            project_id)
                except NotFound:
                    raise ObjectNotFound({'detail': _('Project not found')})
                except ConnectFailure:
                    raise ServiceUnavailable(
                        {'detail': _('Could not connect to openstack')})

                with transaction.atomic():
                    try:
                        ProjectModel.objects.create_project(
                            client=client,
                            openstack_product=openstack_product,
                            openstack_product_cycle=openstack_product_cycle,
                            service_external_id=service_external_id,
                            project_id=project.id,
                            project_domain_id=project.domain_id,
                            disabled=not project.enabled,
                            extras={
                                'name': project.name,
                                'description': project.description,
                                'is_domain': project.is_domain
                            }).save()
                    except RoleDoesNotExist:
                        # TODO: going to the exact settings page and field isn't implemented yet in frontend
                        # on implementation in frontend change section and configuration_id if necessary
                        # (Issue: https://git.fleio.org/fleio/fleio/issues/1922)
                        if plugin_settings.default_role:
                            error_message = _(
                                'Role "{}" does not exist in OpenStack. Set an existing role as default '
                                'role.').format(plugin_settings.default_role)
                        else:
                            error_message = _(
                                'OpenStack role was not set in OpenStack settings -> defaults tab. '
                                'Set an existing role as default role.')
                        raise ConfigException(
                            message=error_message,
                            section='openstack_plugin_defaults',
                            configuration_id='default_role')

        return Response({'detail': _('Ok')})