Пример #1
0
def bind_resources(offering, data, provider):

    # Check that the offering supports binding
    if offering.state != 'uploaded' and not (offering.open and offering.state == 'published'):
        raise PermissionDenied('This offering cannot be modified')

    added_resources = []
    offering_resources = []
    for of_res in offering.resources:
        offering_resources.append(of_res)

    for res in data:
        try:
            resource = Resource.objects.get(name=res['name'], version=res['version'], provider=provider.userprofile.current_organization)
        except:
            raise ValueError('Resource not found: ' + res['name'] + ' ' + res['version'])

        # Check resource state
        if resource.state == 'deleted':
            raise PermissionDenied('Invalid resource, the resource ' + res['name'] + ' ' + res['version'] + ' is deleted')

        # Check open
        if not resource.open and offering.open:
            raise PermissionDenied('It is not allowed to include not open resources in an open offering')

        if not ObjectId(resource.pk) in offering_resources:
            added_resources.append(resource.pk)
        else:
            offering_resources.remove(ObjectId(resource.pk))

    # added_resources contains the resources to be added to the offering
    # and offering_resources the resources to be deleted from the offering

    for add_res in added_resources:
        resource = Resource.objects.get(pk=add_res)
        resource.offerings.append(offering.pk)
        resource.save()
        offering.resources.append(ObjectId(add_res))

    for del_res in offering_resources:
        resource = Resource.objects.get(pk=del_res)
        resource.offerings.remove(offering.pk)
        resource.save()
        offering.resources.remove(del_res)

    offering.offering_description['modified'] = unicode(datetime.now())
    offering.save()

    # Update USDL document if needed
    if offering.open and offering.state == 'published' and len(offering.description_url):
        usdl_generator = USDLGenerator()
        repository_adaptor = unreg_repository_adaptor_factory(offering.description_url)

        if settings.OILAUTH:
            repository_adaptor.set_credentials(provider.userprofile.access_token)

        repository_adaptor.upload(
            'application/rdf+xml',
            usdl_generator.generate_offering_usdl(offering)[0]
        )
Пример #2
0
    def _aggregate_text(self, offering):
        """
        Create a single string for creating the index by extracting text fields
        from the USDL document of the offering
        """
        graph = rdflib.ConjunctiveGraph()

        generator = USDLGenerator()
        graph.parse(data=generator.generate_offering_usdl(offering)[0],
                    format='application/rdf+xml')

        text = offering.name

        for s, p, o in graph:
            if isinstance(o, rdflib.Literal):
                text += ' ' + unicode(o)

        return text
Пример #3
0
    def _aggregate_text(self, offering):
        """
        Create a single string for creating the index by extracting text fields
        from the USDL document of the offering
        """
        graph = rdflib.ConjunctiveGraph()

        generator = USDLGenerator()
        graph.parse(
            data=generator.generate_offering_usdl(offering)[0],
            format='application/rdf+xml'
        )

        text = offering.name

        for s, p, o in graph:
            if isinstance(o, rdflib.Literal):
                text += ' ' + unicode(o)

        return text
Пример #4
0
def publish_offering(user, offering, data):

    # Validate data
    if 'marketplaces' not in data:
        raise ValueError('Publication error: missing required field, marketplaces')

    # Validate the state of the offering
    if not offering.state == 'uploaded':
        raise PermissionDenied('Publication error: The offering ' + offering.name + ' ' + offering.version + ' cannot be published')

    # Validate the offering has enough content to be published
    # Open offerings cannot be published in they do not contain
    # digital assets (applications or resources)
    if offering.open and not len(offering.resources) and not len(offering.applications):
        raise PermissionDenied('Publication error: Open offerings cannot be published if they do not contain at least a digital asset (resource or application)')

    # Check if it possible to publish the offering in a Marketplace
    if not len(Repository.objects.all()) > 0 and len(data['marketplaces']) > 0:
        raise PermissionDenied('Publication error: It is not possible to publish an offering in a Markteplace if no Repositories has been registered')

    # Upload the USDL description of the offering to the repository
    if len(Repository.objects.all()) > 0:
        repository = Repository.objects.get(is_default=True)

        # Generate the USDL of the offering
        generator = USDLGenerator()
        usdl, offering_uri = generator.generate_offering_usdl(offering)

        repository_adaptor = repository_adaptor_factory(repository)
        offering_id = offering.owner_organization.name + '__' + offering.name + '__' + offering.version

        repository_adaptor.set_uri(offering_uri)

        if settings.OILAUTH:
            repository_adaptor.set_credentials(user.userprofile.access_token)

        offering.description_url = repository_adaptor.upload('application/rdf+xml', usdl, name=offering_id)

    # Publish the offering in the selected marketplaces
    for market in data['marketplaces']:
        try:
            m = Marketplace.objects.get(name=market)
        except:
            raise ValueError('Publication error: The marketplace ' + market + ' does not exist')

        market_adaptor = marketadaptor_factory(m, user)

        off_market_name = market_adaptor.add_service(offering)
        offering.marketplaces.append(MarketOffering(
            marketplace=m,
            offering_name=off_market_name
        ))

    # Create revenue sharing models if needed
    build_rs_model(offering)

    offering.state = 'published'
    offering.publication_date = datetime.now()
    offering.save()

    # Update offering indexes
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    se = SearchEngine(index_path)
    se.update_index(offering)
Пример #5
0
def update_offering(user, offering, data):

    # Check if the offering has been published,
    # if published the offering cannot be updated
    if offering.state != 'uploaded' and not offering.open:
        raise PermissionDenied('The offering cannot be edited')

    dir_name = offering.owner_organization.name + '__' + offering.name + '__' + offering.version
    path = os.path.join(settings.MEDIA_ROOT, dir_name)

    # Update the logo
    if 'image' in data:
        logo_path = offering.image_url
        logo_path = os.path.join(settings.BASEDIR, logo_path[1:])

        # Remove the old logo
        os.remove(logo_path)

        # Save the new logo
        _save_encoded_image(path, data['image']['name'], data['image']['data'])
        offering.image_url = settings.MEDIA_URL + dir_name + '/' + data['image']['name']

    # Update the related images
    if 'related_images' in data:

        # Delete old related images
        for img in offering.related_images:
            old_image = os.path.join(settings.BASEDIR, img[1:])
            os.remove(old_image)

        offering.related_images = []

        # Create new images
        for img in data['related_images']:
            _save_encoded_image(path, img['name'], img['data'])
            offering.related_images.append(settings.MEDIA_URL + dir_name + '/' + img['name'])

    if 'offering_description' in data:
        # Create offering USDL
        offering_info = deepcopy(data['offering_description'])
        offering_info['image_url'] = offering.image_url
        offering_info['name'] = offering.name
        offering_info['version'] = offering.version
        offering_info['organization'] = offering.owner_organization.name
        offering_info['base_id'] = offering.pk

        offering_info['created'] = unicode(offering.creation_date)

        mod = unicode(datetime.now())
        offering_info['modified'] = mod

        usdl_generator = USDLGenerator()
        usdl_generator.validate_info(offering_info, offering.owner_organization, open_=offering.open)

        data['offering_description']['modified'] = mod
        offering.offering_description = data['offering_description']

        if offering.open and offering.state == 'published' and len(offering.description_url):
            repository_adaptor = unreg_repository_adaptor_factory(offering.description_url)

            if settings.OILAUTH:
                repository_adaptor.set_credentials(user.userprofile.access_token)

            repository_adaptor.upload(
                'application/rdf+xml',
                usdl_generator.generate_offering_usdl(offering)[0]
            )

    offering.save()

    # Update offering indexes
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    se = SearchEngine(index_path)
    se.update_index(offering)
Пример #6
0
def create_offering(provider, data):
    """
    Creates a new offering including the media files and
    the repository uploads
    """
    profile = provider.userprofile

    # Validate basic fields
    if 'name' not in data or 'version' not in data or 'offering_description' not in data \
            or 'image' not in data:

        missing_fields = ''

        if 'name' not in data:
            missing_fields += ' name'

        if 'version' not in data:
            missing_fields += ' version'

        if 'offering_description' not in data:
            missing_fields += ' offering_description'

        if 'image' not in data:
            missing_fields += ' image'

        raise ValueError('Missing required fields:' + missing_fields)

    if not re.match(re.compile(r'^(?:[1-9]\d*\.|0\.)*(?:[1-9]\d*|0)$'), data['version']):
        raise ValueError('Invalid version format')

    if not is_valid_id(data['name']):
        raise ValueError('Invalid name format')

    # Get organization
    organization = profile.current_organization

    # Check if the offering already exists
    if len(Offering.objects.filter(name=data['name'], owner_organization=organization, version=data['version'])) > 0:
        raise ConflictError('The offering ' + data['name'] + ' version ' + data['version'] + ' already exists')

    # Check if the version of the offering is lower than an existing one
    offerings = Offering.objects.filter(owner_organization=organization, name=data['name'])
    for off in offerings:
        if is_lower_version(data['version'], off.version):
            raise ValueError('A bigger version of the current offering exists')

    is_open = data.get('open', False)

    # If using the idm, get the applications from the request
    if settings.OILAUTH and 'applications' in data:
        # Validate application structure
        for app in data['applications']:
            if 'name' not in app or 'url' not in app or 'id' not in app or 'description' not in app:
                raise ValueError('Missing a required field in application definition')

    # Check the URL to notify the provider
    notification_url = ''
    if 'notification_url' in data:
        if data['notification_url'] == 'default':
            notification_url = organization.notification_url
            if not notification_url:
                raise ValueError('There is not a default notification URL defined for the organization ' + organization.name + '. To configure a default notification URL provide it in the settings menu')
        else:
            # Check the notification URL
            if not is_valid_url(data['notification_url']):
                raise ValueError("Invalid notification URL format: It doesn't seem to be an URL")

            notification_url = data['notification_url']

    # Create the directory for app media
    dir_name = organization.name + '__' + data['name'] + '__' + data['version']
    path = os.path.join(settings.MEDIA_ROOT, dir_name)
    os.makedirs(path)

    # Validate image format
    if not isinstance(data['image'], dict):
        raise TypeError('Invalid image type')

    data['image_url'] = _create_image(dir_name, path, data['image'])

    # Save screen shots
    screenshots = []
    if 'related_images' in data:
        for image in data['related_images']:
            screenshots.append(_create_image(dir_name, path, image))
    else:
        data['related_images'] = []

    # Validate the USDL
    data['open'] = is_open
    data['organization'] = organization

    # Create offering USDL
    offering_info = deepcopy(data['offering_description'])
    offering_info['image_url'] = data['image_url']
    offering_info['name'] = data['name']
    offering_info['version'] = data['version']
    offering_info['organization'] = organization.name
    offering_info['base_id'] = 'pk'

    created = datetime.now()
    offering_info['created'] = unicode(created)
    offering_info['modified'] = unicode(created)

    data['offering_description']['modified'] = unicode(created)

    usdl_generator = USDLGenerator()
    usdl_generator.validate_info(offering_info, organization, open_=is_open)

    # Create the offering
    offering = Offering(
        name=data['name'],
        owner_organization=organization,
        owner_admin_user=provider,
        version=data['version'],
        state='uploaded',
        resources=[],
        comments=[],
        tags=[],
        image_url=data['image_url'],
        related_images=screenshots,
        notification_url=notification_url,
        creation_date=created,
        open=is_open,
        offering_description=data['offering_description']
    )

    if settings.OILAUTH and 'applications' in data:
        offering.applications = data['applications']

    offering.save()

    offering.offering_description['base_id'] = offering.pk
    offering.save()

    if 'resources' in data and len(data['resources']) > 0:
        bind_resources(offering, data['resources'], profile.user)

    # Load offering document to the search index
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    search_engine = SearchEngine(index_path)
    search_engine.create_index(offering)