def _update_actor_balance(self, price): rss = RSS.objects.all()[0] actor = None # Check who is the charging actor (user or organization) if self._purchase.organization_owned: actor = self._purchase.owner_organization else: client = self._purchase.customer actor = Organization.objects.get(actor_id=client.userprofile.actor_id) charge = { 'currency': self._price_model['general_currency'], 'amount': price } # Check balance try: rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager(rss.access_token) exp_manager.update_balance(charge, actor) except HTTPError as e: # Check if it is needed to refresh the access token if e.code == 401: rss._refresh_token() exp_manager.set_credentials(rss.access_token) exp_manager.update_balance(charge, actor) # Check if the error is due to an insufficient balance else: raise e
def delete(self, request, rss): if not request.user.is_staff: return build_response(request, 403, 'Forbidden') # Get rss entry try: rss_model = RSS.objects.get(name=rss) except: return build_response(request, 404, 'Not found') # Delete provider limits rss_factory = RSSManagerFactory(rss_model) exp_manager = rss_factory.get_expenditure_manager(request.user.userprofile.access_token) call_result = _make_rss_request(exp_manager, exp_manager.delete_provider_limit, request.user) if call_result[0]: return build_response(request, call_result[1], call_result[2]) # Delete rs models model_manager = rss_factory.get_model_manager(request.user.userprofile.access_token) call_result = _make_rss_request(model_manager, model_manager.delete_provider_models, request.user) if call_result[0]: return build_response(request, call_result[1], call_result[2]) # Delete rss model rss_model.delete() return build_response(request, 204, 'No content')
def _update_actor_balance(self, price): rss = RSS.objects.all()[0] actor = None # Check who is the charging actor (user or organization) if self._purchase.organization_owned: actor = self._purchase.owner_organization else: client = self._purchase.customer actor = Organization.objects.get( actor_id=client.userprofile.actor_id) charge = { 'currency': self._price_model['general_currency'], 'amount': price } # Check balance try: rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager(rss.access_token) exp_manager.update_balance(charge, actor) except HTTPError as e: # Check if it is needed to refresh the access token if e.code == 401: rss._refresh_token() exp_manager.set_credentials(rss.access_token) exp_manager.update_balance(charge, actor) # Check if the error is due to an insufficient balance else: raise e
def _check_expenditure_limits(self, price): """ Check if the user can purchase the offering depending on its expenditure limits and ir accumulated balance thought the RSS """ # Check is an RSS instance is registered if not RSS.objects.all(): return else: rss = RSS.objects.all()[0] actor = None # Check who is the charging actor (user or organization) actor = self._purchase.owner_organization # Check if the actor has defined expenditure limits if not actor.expenditure_limits: return charge = { 'currency': self._price_model['general_currency'], 'amount': price } # Check balance request_failure = None try: rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager(rss.access_token) exp_manager.check_balance(charge, actor) except HTTPError as e: # Check if it is needed to refresh the access token if e.code == 401: rss._refresh_token() exp_manager.set_credentials(rss.access_token) try: exp_manager.check_balance(charge, actor) # The user may be unauthorized, an error occurs, or the # actor balance is not enough except: request_failure = e # Check if the error is due to an insufficient balance else: request_failure = e except: request_failure = e # Raise the correct failure if request_failure: if type(request_failure) == HTTPError and request_failure.code == 404\ and json.loads(request_failure.read())['exceptionId'] == 'SVC3705': raise Exception( 'There is not enough balance. Check your expenditure limits' ) else: raise request_failure self._expenditure_used = True
def _check_expenditure_limits(self, price): """ Check if the user can purchase the offering depending on its expenditure limits and ir accumulated balance thought the RSS """ # Check is an RSS instance is registered if not RSS.objects.all(): return else: rss = RSS.objects.all()[0] actor = None # Check who is the charging actor (user or organization) actor = self._purchase.owner_organization # Check if the actor has defined expenditure limits if not actor.expenditure_limits: return charge = { 'currency': self._price_model['general_currency'], 'amount': price } # Check balance request_failure = None try: rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager(rss.access_token) exp_manager.check_balance(charge, actor) except HTTPError as e: # Check if it is needed to refresh the access token if e.code == 401: rss._refresh_token() exp_manager.set_credentials(rss.access_token) try: exp_manager.check_balance(charge, actor) # The user may be unauthorized, an error occurs, or the # actor balance is not enough except: request_failure = e # Check if the error is due to an insufficient balance else: request_failure = e except: request_failure = e # Raise the correct failure if request_failure: if type(request_failure) == HTTPError and request_failure.code == 404\ and json.loads(request_failure.read())['exceptionId'] == 'SVC3705': raise Exception('There is not enough balance. Check your expenditure limits') else: raise request_failure self._expenditure_used = True
def update(self, request, org): # Get the organization try: organization = Organization.objects.get(name=org) except: return build_response(request, 404, 'Organization not found') if not request.user.is_active: return build_response(request, 403, 'Forbidden') if not request.user.is_staff and request.user.pk not in organization.managers: return build_response(request, 403, 'Forbidden') try: # Load request data data = json.loads(request.raw_post_data) if 'notification_url' in data: if data['notification_url'] and not is_valid_url(data['notification_url']): raise Exception('Enter a valid URL') organization.notification_url = data['notification_url'] # Load the tax address new_taxaddr = {} if 'tax_address' in data and data['tax_address'] != {}: new_taxaddr = { 'street': data['tax_address']['street'], 'postal': data['tax_address']['postal'], 'city': data['tax_address']['city'], 'country': data['tax_address']['country'] } organization.tax_address = new_taxaddr # Load the payment info new_payment = {} if 'payment_info' in data and data['payment_info'] != {}: number = data['payment_info']['number'] if not is_valid_credit_card(number): if 'number' in organization.payment_info and \ is_hidden_credit_card(number, organization.payment_info['number']): number = organization.payment_info['number'] else: raise Exception('Invalid credit card number') new_payment = { 'type': data['payment_info']['type'], 'number': number, 'expire_year': data['payment_info']['expire_year'], 'expire_month': data['payment_info']['expire_month'], 'cvv2': data['payment_info']['cvv2'] } if 'limits' in data: limits = _check_limits(data['limits']) currency = limits['currency'] # Get default RSS rss = RSS.objects.all()[0] rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager(rss.access_token) try: exp_manager.set_actor_limit(limits, organization) except HTTPError as e: if e.code == 401: rss.refresh_token() exp_manager.set_credentials(rss.access_token) exp_manager.set_actor_limit(limits, organization) else: raise e # Save limits limits['currency'] = currency organization.expenditure_limits = limits organization.payment_info = new_payment organization.save() except Exception as e: msg = 'Invalid JSON content' if e.message: msg = e.message return build_response(request, 400, msg) return build_response(request, 200, 'OK')
def run(self): from wstore.rss_adaptor.rss_manager_factory import RSSManagerFactory rss_factory = RSSManagerFactory(self.rss) r = rss_factory.get_rss_adaptor() r.send_cdr(self.cdr)
def build_rs_model(offering): # Get RSS object if not len(RSS.objects.all()): return rss = RSS.objects.all()[0] if rss.api_version == 1: return rss_factory = RSSManagerFactory(rss) model_manager = rss_factory.get_model_manager(rss.access_token) # Build basic RS model # Get applied class revenue_class = None for plan in (offering.offering_description['pricing']['price_plans']): if 'price_components' in plan: for comp in plan['price_components']: if 'price_function' in comp: revenue_class = 'use' break try: unit = Unit.objects.get(name=comp['unit']) except: raise Exception('Unsupported unit in price plan model') if unit.defined_model == 'pay per use': revenue_class = 'use' break elif unit.defined_model == 'subscription': revenue_class = 'subscription' elif unit.defined_model == 'single payment' and revenue_class is None: revenue_class = 'single-payment' if revenue_class == 'use': break if revenue_class is not None: # Create new provider in the RSS prov_manager = rss_factory.get_provider_manager(rss.access_token) provider_info = { 'provider_id': offering.owner_organization.actor_id, 'provider_name': offering.owner_organization.name } try: prov_manager.register_provider(provider_info) except HTTPError as e: if e.code == 401: rss.refresh_token() prov_manager.set_credentials(rss.access_token) try: prov_manager.register_provider(provider_info) except: pass model_info = {} for model in rss.revenue_models: if model.revenue_class == revenue_class: model_info['aggregatorValue'] = model.percentage break model_info['ownerValue'] = 100 - model_info['aggregatorValue'] model_info['productClass'] = offering.owner_organization.name + '/' + offering.name + '/' + offering.version try: model_manager.create_revenue_model(model_info, offering.owner_organization.actor_id) except HTTPError as e: if e.code == 401: rss.refresh_token() model_manager.set_credentials(rss.access_token) model_manager.create_revenue_model(model_info, offering.owner_organization.actor_id) else: raise Exception('Revenue Sharing model for offering ' + offering.owner_organization.name + ' ' + offering.name + ' ' + offering.version)
def update(self, request, username): if not request.user.is_staff and not request.user.username == username: return build_response(request, 403, 'Forbidden') data = json.loads(request.raw_post_data) # Update the user try: user = User.objects.get(username=username) # Get the user profile user_profile = UserProfile.objects.get(user=user) # If WStore is not integrated with the accounts enabler # update user info and roles if not settings.OILAUTH: if request.user.is_staff and 'roles' in data: # The user cannot change its roles if 'admin' in data['roles'] and request.user.is_staff: user.is_staff = True if 'provider' in data['roles']: # Append the provider role to the user orgs = [] for o in user_profile.organizations: if Organization.objects.get(pk=o['organization']).name == user.username \ and 'provider' not in o['roles']: o['roles'].append('provider') orgs.append(o) user_profile.organizations = orgs elif 'provider' not in data[ 'roles'] and 'provider' in user_profile.get_user_roles( ): # Remove the provider role from the user info orgs = [] for o in user_profile.organizations: if Organization.objects.get( pk=o['organization'] ).name == user.username: o['roles'].remove('provider') orgs.append(o) else: orgs.append(o) user_profile.organizations = orgs if 'notification_url' in data and 'provider' in user_profile.get_user_roles( ): user_org = Organization.objects.get(name=user.username) user_org.notification_url = data['notification_url'] user_org.save() if 'password' in data: user.set_password(data['password']) if 'first_name' in data and 'last_name' in data: user.first_name = data['first_name'] user.last_name = data['last_name'] user_profile.complete_name = data[ 'first_name'] + ' ' + data['last_name'] elif 'complete_name' in data: user_profile.complete_name = data['complete_name'] else: user_org = Organization.objects.get( actor_id=user.userprofile.actor_id) if 'notification_url' in data and 'provider' in user_profile.get_user_roles( ): user_org.notification_url = data['notification_url'] user_org.save() # Check if expenditure limits are included in the request if 'limits' in data and data['limits']: limits = _check_limits(data['limits']) currency = limits['currency'] # Get default RSS instance try: rss_instance = RSS.objects.all()[0] except: raise Exception( 'No RSS instance registered: An RSS instance is needed for setting up expenditure limits' ) # Create limits in the RSS try: rss_factory = RSSManagerFactory(rss_instance) exp_manager = rss_factory.get_expenditure_manager( rss_instance.access_token) exp_manager.set_actor_limit(limits, user.userprofile) except HTTPError as e: if e.code == 401: rss_instance.refresh_token() exp_manager.set_credentials( rss_instance.access_token) exp_manager.set_actor_limit( limits, user.userprofile) else: raise e # Save limits limits['currency'] = currency user_org.expenditure_limits = limits user_org.save() if 'tax_address' in data: user_profile.tax_address = { 'street': data['tax_address']['street'], 'postal': data['tax_address']['postal'], 'city': data['tax_address']['city'], 'country': data['tax_address']['country'] } else: # the update is absolute so if no tax address provided it is deleted user_profile.tax_address = {} if 'payment_info' in data: number = data['payment_info']['number'] if not is_valid_credit_card(number): if 'number' in user_profile.payment_info and \ is_hidden_credit_card(number, user_profile.payment_info['number']): number = user_profile.payment_info['number'] else: raise Exception('') user_profile.payment_info = { 'type': data['payment_info']['type'], 'number': number, 'expire_month': data['payment_info']['expire_month'], 'expire_year': data['payment_info']['expire_year'], 'cvv2': data['payment_info']['cvv2'] } else: # the update is absolute so if no payment info provided it is deleted user_profile.payment_info = {} user.save() user_profile.save() except Exception as e: msg = 'Invalid content' if e.message: msg = e.message return build_response(request, 400, msg) return build_response(request, 200, 'OK')
def update(self, request, rss): """ Makes a partial update, only name, limits and default selection """ # Check if the user is staff if not request.user.is_staff: return build_response(request, 403, 'Forbidden') # Check rss try: rss_model = RSS.objects.get(name=rss) except: return build_response(request, 404, 'Not found') # Get data try: data = json.loads(request.raw_post_data) except: return build_response(request, 400, 'Invalid JSON data') # Check the name if 'name' in data and data['name'].lower() != rss.lower(): # Check that the name does not exist exist = True try: RSS.objects.get(name=data['name']) except: exist = False if exist: return build_response(request, 400, 'The selected name is in use') rss_model.name = data['name'] rss_model.save() limits = {} # Check if limits has been provided if 'limits' in data: limits = _check_limits(data['limits']) sharing_models = [] if 'models' in data: try: sharing_models = _check_revenue_models(data['models']) except Exception as e: return build_response(request, 400, unicode(e)) # Update expenditure limits rss_factory = RSSManagerFactory(rss_model) if limits: old_limits = rss_model.expenditure_limits rss_model.expenditure_limits = limits rss_model.save() # Make the update request exp_manager = rss_factory.get_expenditure_manager(request.user.userprofile.access_token) call_result = _make_rss_request(exp_manager, exp_manager.set_provider_limit, request.user) if call_result[0]: # Reset expenditure limits rss_model.expenditure_limits = old_limits return build_response(request, call_result[1], call_result[2]) # Update revenue sharing models if len(sharing_models): rss_model.revenue_models = [] if rss_model.api_version == 1: model_manager = rss_factory.get_model_manager(request.user.userprofile.access_token) # Update the models for model in sharing_models: revenue_model = RevenueModel( revenue_class=model['class'], percentage=Decimal(model['percentage']) ) if rss_model.api_version == 1: def call_model_creation(): model_manager.update_revenue_model(model) call_result = _make_rss_request(model_manager, call_model_creation, request.user) if call_result[0]: return build_response(request, call_result[1], call_result[2]) rss_model.revenue_models.append(revenue_model) # Update credentials rss_model.access_token = request.user.userprofile.access_token rss_model.refresh_token = request.user.userprofile.refresh_token # Save the model rss_model.save() return build_response(request, 200, 'OK')
def create(self, request): # Only the admin can register new RSS instances if not request.user.is_staff: return build_response(request, 403, 'Forbidden') data = json.loads(request.raw_post_data) if 'name' not in data or 'host' not in data or 'api_version' not in data: msg = 'RSS creation error: Missing a required field' if 'name' not in data: msg += ', name' if 'host' not in data: msg += ', host' if 'api_version' not in data: msg += ', api_version' return build_response(request, 400, msg) # Check name regex if not is_valid_id(data['name']): return build_response(request, 400, 'RSS creation error: Invalid name format') # Check url regex if not is_valid_url(data['host']): return build_response(request, 400, 'RSS creation error: Invalid URL format') # Check api_version format try: api_version = int(data['api_version']) except: return build_response(request, 400, 'RSS creation error: Invalid api_version format, must be an integer (1 or 2)') if api_version != 1 and api_version != 2: return build_response(request, 400, 'RSS creation error: Invalid api_version, must be 1 or 2') # Check if the information provided is not already registered if len(RSS.objects.all()) > 0: return build_response(request, 409, 'RSS creation error: There is a RSS instance already registered') limits = {} cont = Context.objects.all()[0] # Check request limits if 'limits' in data: try: limits = _check_limits(data['limits']) except Exception as e: return build_response(request, 400, unicode(e)) if not len(limits): # Set default limits limits = { 'currency': cont.allowed_currencies['default'], 'perTransaction': 10000, 'weekly': 100000, 'daily': 10000, 'monthly': 100000 } # Check revenue sharing models sharing_models = [] if 'models' in data: try: sharing_models = _check_revenue_models(data['models']) except Exception as e: return build_response(request, 400, unicode(e)) else: # Set default revenue models sharing_models = [{ 'class': 'single-payment', 'percentage': 10.0 }, { 'class': 'subscription', 'percentage': 20.0 }, { 'class': 'use', 'percentage': 30.0 }] # Build revenue models db_revenue_models = [] for model in sharing_models: db_revenue_models.append(RevenueModel( revenue_class=model['class'], percentage=Decimal(model['percentage']) )) if not data['host'].endswith('/'): data['host'] += '/' # Create the new entry rss = RSS.objects.create( name=data['name'], host=data['host'], api_version=api_version, expenditure_limits=limits, revenue_models=db_revenue_models, aggregator_id=request.user.email ) rss_factory = RSSManagerFactory(rss) # Create a new provider if needed if api_version == 2: prov_manager = rss_factory.get_provider_manager(request.user.userprofile.access_token) provider_info = { 'provider_id': settings.STORE_NAME.lower() + '-provider', 'provider_name': settings.STORE_NAME + '-Provider' } call_result = _make_rss_request(prov_manager, prov_manager.register_provider, request.user, provider_info) if call_result[0]: rss.delete() # Return error response return build_response(request, call_result[1], call_result[2]) exp_manager = rss_factory.get_expenditure_manager(request.user.userprofile.access_token) # Create default expenditure limits call_result = _make_rss_request(exp_manager, exp_manager.set_provider_limit, request.user) if call_result[0]: rss.delete() # Return error response return build_response(request, call_result[1], call_result[2]) # Create default revenue sharing models if api_version == 1: model_manager = rss_factory.get_model_manager(rss, request.user) model_created = False for model in sharing_models: def call_model_creation(): model_manager.create_revenue_model(model) call_result = _make_rss_request(model_manager, call_model_creation, request.user) if call_result[0] and not model_created: rss.delete() return build_response(request, call_result[1], call_result[2]) elif not call_result[0]: model_created = True # The request has been success so the used credentials are valid # Store the credentials for future access rss.access_token = request.user.userprofile.access_token rss.refresh_token = request.user.userprofile.refresh_token rss.save() return build_response(request, 201, 'Created')
def update(self, request, org): # Get the organization try: organization = Organization.objects.get(name=org) except: return build_response(request, 404, 'Organization not found') if not request.user.is_active: return build_response(request, 403, 'Forbidden') if not request.user.is_staff and request.user.pk not in organization.managers: return build_response(request, 403, 'Forbidden') try: # Load request data data = json.loads(request.raw_post_data) if 'notification_url' in data: if data['notification_url'] and not is_valid_url( data['notification_url']): raise Exception('Enter a valid URL') organization.notification_url = data['notification_url'] # Load the tax address new_taxaddr = {} if 'tax_address' in data and data['tax_address'] != {}: new_taxaddr = { 'street': data['tax_address']['street'], 'postal': data['tax_address']['postal'], 'city': data['tax_address']['city'], 'country': data['tax_address']['country'] } organization.tax_address = new_taxaddr # Load the payment info new_payment = {} if 'payment_info' in data and data['payment_info'] != {}: number = data['payment_info']['number'] if not is_valid_credit_card(number): if 'number' in organization.payment_info and \ is_hidden_credit_card(number, organization.payment_info['number']): number = organization.payment_info['number'] else: raise Exception('Invalid credit card number') new_payment = { 'type': data['payment_info']['type'], 'number': number, 'expire_year': data['payment_info']['expire_year'], 'expire_month': data['payment_info']['expire_month'], 'cvv2': data['payment_info']['cvv2'] } if 'limits' in data: limits = _check_limits(data['limits']) currency = limits['currency'] # Get default RSS rss = RSS.objects.all()[0] rss_factory = RSSManagerFactory(rss) exp_manager = rss_factory.get_expenditure_manager( rss.access_token) try: exp_manager.set_actor_limit(limits, organization) except HTTPError as e: if e.code == 401: rss.refresh_token() exp_manager.set_credentials(rss.access_token) exp_manager.set_actor_limit(limits, organization) else: raise e # Save limits limits['currency'] = currency organization.expenditure_limits = limits organization.payment_info = new_payment organization.save() except Exception as e: msg = 'Invalid JSON content' if e.message: msg = e.message return build_response(request, 400, msg) return build_response(request, 200, 'OK')
def update(self, request, username): if not request.user.is_staff and not request.user.username == username: return build_response(request, 403, 'Forbidden') data = json.loads(request.raw_post_data) # Update the user try: user = User.objects.get(username=username) # Get the user profile user_profile = UserProfile.objects.get(user=user) # If WStore is not integrated with the accounts enabler # update user info and roles if not settings.OILAUTH: if request.user.is_staff and 'roles' in data: # The user cannot change its roles if 'admin' in data['roles'] and request.user.is_staff: user.is_staff = True if 'provider' in data['roles']: # Append the provider role to the user orgs = [] for o in user_profile.organizations: if Organization.objects.get(pk=o['organization']).name == user.username \ and 'provider' not in o['roles']: o['roles'].append('provider') orgs.append(o) user_profile.organizations = orgs elif 'provider' not in data['roles'] and 'provider' in user_profile.get_user_roles(): # Remove the provider role from the user info orgs = [] for o in user_profile.organizations: if Organization.objects.get(pk=o['organization']).name == user.username: o['roles'].remove('provider') orgs.append(o) else: orgs.append(o) user_profile.organizations = orgs if 'notification_url' in data and 'provider' in user_profile.get_user_roles(): user_org = Organization.objects.get(name=user.username) user_org.notification_url = data['notification_url'] user_org.save() if 'password' in data: user.set_password(data['password']) if 'first_name' in data and 'last_name' in data: user.first_name = data['first_name'] user.last_name = data['last_name'] user_profile.complete_name = data['first_name'] + ' ' + data['last_name'] elif 'complete_name' in data: user_profile.complete_name = data['complete_name'] else: user_org = Organization.objects.get(actor_id=user.userprofile.actor_id) if 'notification_url' in data and 'provider' in user_profile.get_user_roles(): user_org.notification_url = data['notification_url'] user_org.save() # Check if expenditure limits are included in the request if 'limits' in data and data['limits']: limits = _check_limits(data['limits']) currency = limits['currency'] # Get default RSS instance try: rss_instance = RSS.objects.all()[0] except: raise Exception('No RSS instance registered: An RSS instance is needed for setting up expenditure limits') # Create limits in the RSS try: rss_factory = RSSManagerFactory(rss_instance) exp_manager = rss_factory.get_expenditure_manager(rss_instance.access_token) exp_manager.set_actor_limit(limits, user.userprofile) except HTTPError as e: if e.code == 401: rss_instance.refresh_token() exp_manager.set_credentials(rss_instance.access_token) exp_manager.set_actor_limit(limits, user.userprofile) else: raise e # Save limits limits['currency'] = currency user_org.expenditure_limits = limits user_org.save() if 'tax_address' in data: user_profile.tax_address = { 'street': data['tax_address']['street'], 'postal': data['tax_address']['postal'], 'city': data['tax_address']['city'], 'country': data['tax_address']['country'] } else: # the update is absolute so if no tax address provided it is deleted user_profile.tax_address = {} if 'payment_info' in data: number = data['payment_info']['number'] if not is_valid_credit_card(number): if 'number' in user_profile.payment_info and \ is_hidden_credit_card(number, user_profile.payment_info['number']): number = user_profile.payment_info['number'] else: raise Exception('') user_profile.payment_info = { 'type': data['payment_info']['type'], 'number': number, 'expire_month': data['payment_info']['expire_month'], 'expire_year': data['payment_info']['expire_year'], 'cvv2': data['payment_info']['cvv2'] } else: # the update is absolute so if no payment info provided it is deleted user_profile.payment_info = {} user.save() user_profile.save() except Exception as e: msg = 'Invalid content' if e.message: msg = e.message return build_response(request, 400, msg) return build_response(request, 200, 'OK')