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()
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()
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)
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)
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)