Example #1
0
    def validate_upgrade(self, provider, product_spec):

        if 'version' in product_spec and 'productSpecCharacteristic' in product_spec:
            # Extract product needed characteristics
            asset_t, media_type, url, asset_id = self.parse_characteristics(product_spec)
            is_digital = asset_t is not None and media_type is not None and url is not None

            if is_digital:
                asset, lock = self._get_upgrading_asset(asset_t, url, product_spec['id'])

                self._to_downgrade = asset

                self._validate_product_characteristics(asset, provider, asset_t, media_type)

                # Check product version
                if not is_valid_version(product_spec['version']):
                    raise ProductError('The field version does not have a valid format')

                if not is_lower_version(asset.old_versions[-1].version, product_spec['version']):
                    raise ProductError('The provided version is not higher that the previous one')

                # Attach new info
                asset.version = product_spec['version']
                asset.save()

                # Release asset lock
                lock.unlock_document()
def upgrade_resource(resource, data, file_=None):

    # Validate data
    if not "version" in data:
        raise ValueError("Missing a required field: Version")

    # Check version format
    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_lower_version(resource.version, data["version"]):
        raise ValueError(
            "The new version cannot be lower that the current version: " + data["version"] + " - " + resource.version
        )

    # Check resource state
    if resource.state == "deleted":
        raise PermissionDenied("Deleted resources cannot be upgraded")

    # Save the old version
    resource.old_versions.append(
        ResourceVersion(
            version=resource.version, resource_path=resource.resource_path, download_link=resource.download_link
        )
    )

    # Update new version number
    resource.version = data["version"]

    # Update offerings
    if file_ or "content" in data:
        if file_:
            file_content = file_
        else:
            file_content = data["content"]

        # Create new file
        resource.resource_path = _save_resource_file(
            resource.provider.name, resource.name, resource.version, file_content
        )
        resource.download_link = ""
    elif "link" in data:
        if not is_valid_url(data["link"]):
            raise ValueError("Invalid URL format")

        resource.download_link = data["link"]
        resource.resource_path = ""
    else:
        raise ValueError("No resource has been provided")

    resource.save()
Example #3
0
def upgrade_resource(resource, data, file_=None):

    # Validate data
    if not 'version' in data:
        raise ValueError('Missing a required field: Version')

    # Check version format
    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_lower_version(resource.version, data['version']):
        raise ValueError('The new version cannot be lower that the current version: ' + data['version'] + ' - ' + resource.version)

    # Check resource state
    if resource.state == 'deleted':
        raise PermissionDenied('Deleted resources cannot be upgraded')

    # Save the old version
    resource.old_versions.append(ResourceVersion(
        version=resource.version,
        resource_path=resource.resource_path,
        download_link=resource.download_link
    ))

    # Update new version number
    resource.version = data['version']

    # Update offerings
    if file_ or 'content' in data:
        if file_:
            file_content = file_
        else:
            file_content = data['content']

        # Create new file
        resource.resource_path = _save_resource_file(resource.provider.name, resource.name, resource.version, file_content)
        resource.download_link = ''
    elif 'link' in data:
        if not is_valid_url(data['link']):
            raise ValueError('Invalid URL format')

        resource.download_link = data['link']
        resource.resource_path = ''
    else:
        raise ValueError('No resource has been provided')

    resource.save()
Example #4
0
    def create(self, request):

        user = request.user
        content_type = get_content_type(request)[0]

        try:
            data = json.loads(request.raw_post_data)
            payment_info = {}

            if isinstance(data['offering'], dict):
                id_ = data['offering']
                org = Organization.objects.get(name=id_['organization'])
                offering = Offering.objects.get(owner_organization=org, name=id_['name'], version=id_['version'])
            else:
                offering = Offering.objects.get(description_url=data['offering'])

            if 'tax_address' in data:
                payment_info['tax_address'] = data['tax_address']

            payment_info['payment_method'] = data['payment']['method']

            if 'credit_card' in data['payment']:
                payment_info['credit_card'] = data['payment']['credit_card']

            # Get terms and conditions flag
            payment_info['accepted'] = data.get('conditions_accepted', False)

            # Check the selected price plan
            update_plan = False
            developer_plan = False
            if 'plan_label' in data:
                payment_info['plan'] = data['plan_label']
                # Classify the plan
                # Check if the plan is an update
                if data['plan_label'].lower() == 'update':
                    update_plan = True

                # Check if the plan is a developer purchase
                elif data['plan_label'].lower() == 'developer':
                    developer_plan = True

            # Check if the user is purchasing for an organization

            org_owned = True
            if user.userprofile.is_user_org():
                org_owned = False

            # Check if the user has the customer role for the organization
            roles = user.userprofile.get_current_roles()
            if org_owned:

                if not 'customer' in roles and not developer_plan:
                    return build_response(request, 403, 'Forbidden')

                # Load the purchased offerings if it is an update in
                # order to check versions later
                if update_plan:
                    purchased_offerings = user.userprofile.current_organization.offerings_purchased

            elif update_plan:
                purchased_offerings = user.userprofile.offerings_purchased
                    
            # Check if the plan is an update
            if update_plan:
                # Check if the user has purchased a previous version
                found = False
                offerings = Offering.objects.filter(owner_organization=offering.owner_organization, name=offering.name)

                for off in offerings:
                    if off.pk in purchased_offerings and is_lower_version(off.version, offering.version):
                        found = True
                        break

                if not found:
                    return build_response(request, 403, 'Forbidden')

            if developer_plan and not 'developer' in roles:
                    return build_response(request, 403, 'Forbidden')

            response_info = create_purchase(user, offering, org_owned=org_owned, payment_info=payment_info)
        except Exception as e:
            # Check if the offering has been paid before the exception has been raised
            paid = False

            if org_owned:
                if offering.pk in request.user.userprofile.current_organization.offerings_purchased:
                    paid = True
                    response_info = Purchase.objects.get(owner_organization=request.user.userprofile.current_organization, offering=offering)
            else:
                if offering.pk in request.user.userprofile.offerings_purchased:
                    paid = True
                    response_info = Purchase.objects.get(customer=request.user, offering=offering, organization_owned=False)

            if not paid:
                return build_response(request, 400, unicode(e))

        response = {}
        # If the value returned by the create_purchase method is a string means that
        # the purchase is not ended and need user confirmation. response_info contains
        # the URL where redirect the user
        if isinstance(response_info, str) or isinstance(response_info, unicode):
            response['redirection_link'] = response_info
            status = 200
        else:  # The purchase is finished so the download links are returned
            # Load download resources URL

            response['resources'] = []

            for res in offering.resources:
                r = store_resource.objects.get(pk=res)

                # Check if the resource has been uploaded to the store or if is
                # in an external applications server
                if r.resource_path != '':
                    response['resources'].append(r.resource_path)
                elif r.download_link != '':
                    response['resources'].append(r.download_link)

            # Load bill URL
            response['bill'] = response_info.bill
            status = 201

        # Check if it is needed to redirect the user
        token = offering.pk + user.pk

        site = get_current_site(request)
        context = Context.objects.get(site=site)

        if token in context.user_refs:
            redirect_uri = context.user_refs[token]['redirect_uri']
            del(context.user_refs[token])
            context.save()
            response['client_redirection_uri'] = redirect_uri

        return HttpResponse(json.dumps(response), status=status, mimetype=content_type)
Example #5
0
def create_offering(provider, json_data):

    profile = provider.userprofile
    data = {}
    if not 'name' in json_data or not 'version' in json_data:
        raise ValueError('Missing required fields')

    data['name'] = json_data['name']
    data['version'] = json_data['version']

    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
    existing = True

    try:
        Offering.objects.get(name=data['name'], owner_organization=organization, version=data['version'])
    except:
        existing = False

    if existing:
        raise Exception('The offering 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 = json_data.get('open', False)

    # If using the idm, get the applications from the request
    if settings.OILAUTH:

        # Validate application structure
        data['applications'] = []

        for app in json_data['applications']:
            data['applications'].append({
                'name': app['name'],
                'url': app['url'],
                'id': app['id'],
                'description': app['description']
            })

    data['related_images'] = []

    # Check the URL to notify the provider
    notification_url = ''

    if 'notification_url' in json_data:
        if json_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(json_data['notification_url']):
                raise ValueError("Invalid notification URL format: It doesn't seem to be an URL")

            notification_url = json_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)

    if not 'image' in json_data:
        raise ValueError('Missing required field: Logo')

    if not isinstance(json_data['image'], dict):
        raise TypeError('Invalid image type')

    image = json_data['image']

    if not 'name' in image or not 'data' in image:
        raise ValueError('Missing required field in image')

    # Save the application image or logo
    f = open(os.path.join(path, image['name']), "wb")
    dec = base64.b64decode(image['data'])
    f.write(dec)
    f.close()

    data['image_url'] = settings.MEDIA_URL + dir_name + '/' + image['name']
    # Save screen shots
    if 'related_images' in json_data:
        for image in json_data['related_images']:

            # images must be encoded in base64 format
            f = open(os.path.join(path, image['name']), "wb")
            dec = base64.b64decode(image['data'])
            f.write(dec)
            f.close()

            data['related_images'].append(settings.MEDIA_URL + dir_name + '/' + image['name'])

    # Save USDL document
    # If the USDL itself is provided

    if 'offering_description' in json_data:
        usdl_info = json_data['offering_description']

        repository = Repository.objects.get(name=json_data['repository'])
        repository_adaptor = RepositoryAdaptor(repository.host, 'storeOfferingCollection')
        offering_id = organization.name + '__' + data['name'] + '__' + data['version']

        usdl = usdl_info['data']
        data['description_url'] = repository_adaptor.upload(usdl_info['content_type'], usdl_info['data'], name=offering_id)

    # If the USDL is already uploaded in the repository
    elif 'description_url' in json_data:

        # Check that the link to USDL is unique since could be used to
        # purchase offerings from Marketplace
        usdl_info = {}
        usdl_url = json_data['description_url']
        off = Offering.objects.filter(description_url=usdl_url)

        if len(off) != 0:
            raise ValueError('The provided USDL description is already registered')

        # Download the USDL from the repository
        repository_adaptor = RepositoryAdaptor(usdl_url)
        accept = "text/plain; application/rdf+xml; text/turtle; text/n3"

        usdl = repository_adaptor.download(content_type=accept)
        usdl_info['content_type'] = usdl['content_type']

        usdl = usdl['data']
        data['description_url'] = usdl_url

    # If the USDL is going to be created
    elif 'offering_info' in json_data:

        _validate_offering_info(json_data['offering_info'])

        offering_info = json_data['offering_info']
        offering_info['image_url'] = data['image_url']
        offering_info['name'] = data['name']

        repository = Repository.objects.get(name=json_data['repository'])

        offering_info['base_uri'] = repository.host

        usdl = _create_basic_usdl(offering_info)
        usdl_info = {
            'content_type': 'application/rdf+xml'
        }

        repository_adaptor = RepositoryAdaptor(repository.host, 'storeOfferingCollection')
        offering_id = organization.name + '__' + data['name'] + '__' + data['version']
        data['description_url'] = repository_adaptor.upload(usdl_info['content_type'], usdl, name=offering_id)
    else:
        raise Exception('No USDL description provided')

    # Validate the USDL
    data['open'] = is_open
    data['organization'] = organization
    valid = validate_usdl(usdl, usdl_info['content_type'], data)

    if not valid[0]:
        raise Exception(valid[1])

    # Check new currencies used
    if len(valid) > 2:
        new_curr = valid[2]

        # Set the currency as used
        cont = Context.objects.all()[0]
        currency = None
        # Search the currency
        for c in cont.allowed_currencies['allowed']:
            if c['currency'].lower() == new_curr.lower():
                currency = c
                break

        cont.allowed_currencies['allowed'].remove(currency)
        currency['in_use'] = True
        cont.allowed_currencies['allowed'].append(currency)
        cont.save()

    # Serialize and store USDL info in json-ld format
    graph = rdflib.Graph()
    rdf_format = usdl_info['content_type']

    if rdf_format == 'text/turtle' or rdf_format == 'text/plain':
            rdf_format = 'n3'
    elif rdf_format == 'application/json':
            rdf_format = 'json-ld'

    graph.parse(data=usdl, format=rdf_format)
    data['offering_description'] = graph.serialize(format='json-ld', auto_compact=True)

    # Create the offering
    offering = Offering.objects.create(
        name=data['name'],
        owner_organization=organization,
        owner_admin_user=provider,
        version=data['version'],
        state='uploaded',
        description_url=data['description_url'],
        resources=[],
        comments=[],
        tags=[],
        image_url=data['image_url'],
        related_images=data['related_images'],
        offering_description=json.loads(data['offering_description']),
        notification_url=notification_url,
        creation_date=datetime.now(),
        open=is_open
    )

    if settings.OILAUTH:
        offering.applications = data['applications']
        offering.save()

    if 'resources' in json_data and len(json_data['resources']) > 0:
        bind_resources(offering, json_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)
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)
Example #7
0
    def create(self, request):

        user = request.user
        content_type = get_content_type(request)[0]

        try:
            data = json.loads(request.raw_post_data)
            payment_info = {}

            if isinstance(data['offering'], dict):
                id_ = data['offering']
                org = Organization.objects.get(name=id_['organization'])
                offering = Offering.objects.get(owner_organization=org, name=id_['name'], version=id_['version'])
            else:
                offering = Offering.objects.get(description_url=data['offering'])

            if 'tax_address' in data:
                payment_info['tax_address'] = data['tax_address']

            payment_info['payment_method'] = data['payment']['method']

            if 'credit_card' in data['payment']:
                payment_info['credit_card'] = data['payment']['credit_card']

            # Get terms and conditions flag
            payment_info['accepted'] = data.get('conditions_accepted', False)

            # Check the selected price plan
            update_plan = False
            developer_plan = False
            if 'plan_label' in data:
                payment_info['plan'] = data['plan_label']
                # Classify the plan
                # Check if the plan is an update
                if data['plan_label'].lower() == 'update':
                    update_plan = True

                # Check if the plan is a developer purchase
                elif data['plan_label'].lower() == 'developer':
                    developer_plan = True

            # Check if the user is purchasing for an organization

            org_owned = True
            if user.userprofile.is_user_org():
                org_owned = False

            # Check if the user has the customer role for the organization
            roles = user.userprofile.get_current_roles()
            if org_owned:

                if not 'customer' in roles and not developer_plan:
                    return build_response(request, 403, 'Forbidden')

                # Load the purchased offerings if it is an update in
                # order to check versions later
                if update_plan:
                    purchased_offerings = user.userprofile.current_organization.offerings_purchased

            elif update_plan:
                purchased_offerings = user.userprofile.offerings_purchased
                    
            # Check if the plan is an update
            if update_plan:
                # Check if the user has purchased a previous version
                found = False
                offerings = Offering.objects.filter(owner_organization=offering.owner_organization, name=offering.name)

                for off in offerings:
                    if off.pk in purchased_offerings and is_lower_version(off.version, offering.version):
                        found = True
                        break

                if not found:
                    return build_response(request, 403, 'Forbidden')

            if developer_plan and not 'developer' in roles:
                    return build_response(request, 403, 'Forbidden')

            response_info = create_purchase(user, offering, org_owned=org_owned, payment_info=payment_info)
        except Exception as e:
            # Check if the offering has been paid before the exception has been raised
            paid = False

            if org_owned:
                if offering.pk in request.user.userprofile.current_organization.offerings_purchased:
                    paid = True
                    response_info = Purchase.objects.get(owner_organization=request.user.userprofile.current_organization, offering=offering)
            else:
                if offering.pk in request.user.userprofile.offerings_purchased:
                    paid = True
                    response_info = Purchase.objects.get(customer=request.user, offering=offering, organization_owned=False)

            if not paid:
                return build_response(request, 400, unicode(e))

        response = {}
        # If the value returned by the create_purchase method is a string means that
        # the purchase is not ended and need user confirmation. response_info contains
        # the URL where redirect the user
        if isinstance(response_info, str) or isinstance(response_info, unicode):
            response['redirection_link'] = response_info
            status = 200
        else:  # The purchase is finished so the download links are returned
            # Load download resources URL

            response['resources'] = []

            for res in offering.resources:
                r = store_resource.objects.get(pk=res)

                # Check if the resource has been uploaded to the store or if is
                # in an external applications server
                if r.resource_path != '':
                    response['resources'].append(r.resource_path)
                elif r.download_link != '':
                    response['resources'].append(r.download_link)

            # Load bill URL
            response['bill'] = response_info.bill
            status = 201

        # Check if it is needed to redirect the user
        token = offering.pk + user.pk

        site = get_current_site(request)
        context = Context.objects.get(site=site)

        if token in context.user_refs:
            redirect_uri = context.user_refs[token]['redirect_uri']
            del(context.user_refs[token])
            context.save()
            response['client_redirection_uri'] = redirect_uri

        return HttpResponse(json.dumps(response), status=status, mimetype=content_type)
Example #8
0
    def create(self, request):

        user = request.user
        content_type = get_content_type(request)[0]

        if content_type == 'application/json':

            try:
                data = json.loads(request.raw_post_data)
                payment_info = {}

                if isinstance(data['offering'], dict):
                    id_ = data['offering']
                    org = Organization.objects.get(name=id_['organization'])
                    offering = Offering.objects.get(owner_organization=org, name=id_['name'], version=id_['version'])
                else:
                    offering = Offering.objects.get(description_url=data['offering'])

                if 'tax_address' in data:
                    payment_info['tax_address'] = data['tax_address']

                payment_info['payment_method'] = data['payment']['method']

                if 'credit_card' in data['payment']:
                    payment_info['credit_card'] = data['payment']['credit_card']

                # Check the selected price plan
                update_plan = False
                developer_plan = False
                if 'plan_label' in data:
                    payment_info['plan'] = data['plan_label']
                    # Classify the plan
                    # Check if the plan is an update
                    if data['plan_label'].lower() == 'update':
                        update_plan = True

                    # Check if the plan is a developer purchase
                    elif data['plan_label'].lower() == 'developer':
                        developer_plan = True

                # Check if the user is purchasing for an organization

                org_owned = True
                if user.userprofile.is_user_org():
                    org_owned = False

                # Check if the user has the customer role for the organization
                roles = user.userprofile.get_current_roles()
                if org_owned:

                    if not 'customer' in roles and not developer_plan:
                        return build_response(request, 403, 'Forbidden')

                    # Load the purchased offerings if it is an update in
                    # order to check versions later
                    if update_plan:
                        purchased_offerings = user.userprofile.current_organization.offerings_purchased
                    
                elif update_plan:
                    purchased_offerings = user.userprofile.offerings_purchased
                    
                # Check if the plan is an update
                if update_plan:
                    # Check if the user has purchased a previous version
                    found = False
                    offerings = Offering.objects.filter(owner_organization=offering.owner_organization, name=offering.name)

                    for off in offerings:
                        if off.pk in purchased_offerings and is_lower_version(off.version, offering.version):
                            found = True
                            break

                    if not found:
                        return build_response(request, 403, 'Forbidden')

                if developer_plan and not 'developer' in roles:
                        return build_response(request, 403, 'Forbidden')

                response_info = create_purchase(user, offering, org_owned=org_owned, payment_info=payment_info)
            except Exception, e:
                # Check if the offering has been paid before the exception has been raised
                paid = False

                if org_owned:
                    if offering.pk in request.user.userprofile.current_organization.offerings_purchased:
                        paid = True
                        response_info = Purchase.objects.get(owner_organization=request.user.userprofile.current_organization, offering=offering)
                else:
                    if offering.pk in request.user.userprofile.offerings_purchased:
                        paid = True
                        response_info = Purchase.objects.get(customer=request.user, offering=offering, organization_owned=False)

                if not paid:
                    return build_response(request, 400, e.message)