def get_organization(self): if self.organization_url_kwarg in self.kwargs: queryset = Organization.objects.filter( slug=self.kwargs.get(self.organization_url_kwarg)) if queryset.exists(): return queryset.get() return get_broker()
def get(self, request, *args, **kwargs): provider = get_broker() if fail_direct(request, organization=provider): return super(ProviderRedirectView, self).get( request, *args, **kwargs) kwargs.update({self.slug_url_kwarg: provider}) return RedirectView.get(self, request, *args, **kwargs)
def _read_agreement_file(slug, context=None): import markdown if not context: context = {"organization": get_broker()} source, _ = loader.find_template("saas/agreements/legal_%s.md" % slug) return markdown.markdown(source.render(Context(context)))
def parse_line(line, account_first=False, create_organizations=False): """ Parse an (organization, account, amount) triplet. """ if account_first: look = re.match(r'\s+(?P<account>(\w+:)+)(?P<organization>\w+)'\ r'(\s+(?P<amount>.+))?', line) else: look = re.match(r'\s+(?P<organization>\w+)(?P<account>(:(\w+))+)'\ r'(\s+(?P<amount>.+))?', line) if look: organization_slug = look.group('organization') account = look.group('account') if account.startswith(':'): account = account[1:] if account.endswith(':'): account = account[:-1] amount = look.group('amount') if amount and amount.startswith('$'): locale.setlocale(locale.LC_ALL, 'en_US') amount = long(locale.atof(amount[1:]) * 100) try: if create_organizations: organization, _ = Organization.objects.get_or_create( slug=organization_slug) else: organization = Organization.objects.get(slug=organization_slug) if account_first: organization = get_broker() return (organization, account, amount) except Organization.DoesNotExist: print "Cannot find Organization '%s'" % organization_slug return (None, None, None)
def _read_agreement_file(slug, context=None): import markdown if not context: context = {'organization': get_broker()} # We use context and not context=context in the following statement # such that the code is compatible with Django 1.7 and Django 1.8 return markdown.markdown( render_to_string('saas/agreements/legal_%s.md' % slug, context))
def is_current_provider(organization): # We do a string compare here because both ``Organization`` might come # from a different db. That is if the organization parameter is not # a unicode string itself. slug = '' if isinstance(organization, basestring): slug = organization elif organization: slug = organization.slug return slug == get_broker().slug
def user_reset_password_notice(sender, user, request, back_url, expiration_days, **kwargs): """ A user has reset her password. """ LOGGER.debug("[signal] user_reset_password_notice(user=%s, back_url=%s,"\ " expiration_days=%s)", user, back_url, expiration_days) if SEND_EMAIL: app = get_current_app() site = get_current_site() _send_notification_email(site, [user.email], 'notification/password_reset.eml', context={ 'request': request, 'broker': get_broker(), 'app': app, 'back_url': back_url, 'expiration_days': expiration_days, 'user': get_user_context(user) })
def card_updated_notice(sender, organization, user, old_card, new_card, **kwargs): recipients, bcc = _notified_recipients(organization) app = get_current_app() LOGGER.debug("[signal] card_updated_notice(organization=%s, user=%s,"\ "old_card=%s, new_card=%s)", organization, user, old_card, new_card) if SEND_EMAIL: get_email_backend(connection=app.get_connection()).send( from_email=app.get_from_email(), recipients=recipients, bcc=bcc, template='notification/card_updated.eml', context={ 'broker': get_broker(), 'app': app, 'organization': organization, 'user': get_user_context(user), 'old_card': old_card, 'new_card': new_card })
def card_updated_notice(sender, organization, user, old_card, new_card, **kwargs): recipients, bcc = _notified_recipients(organization, 'card_updated') LOGGER.debug("[signal] card_updated_notice(organization=%s, user=%s,"\ "old_card=%s, new_card=%s)", organization, user, old_card, new_card) if SEND_EMAIL and recipients: broker = get_broker() broker_recipients, broker_bcc = _notified_recipients(broker, 'card_updated') app = get_current_app() site = get_current_site() if broker.email and broker.email != site.get_from_email(): reply_to = broker.email _send_notification_email(site, recipients, 'notification/card_updated.eml', reply_to=reply_to, bcc=bcc + broker_recipients + broker_bcc, context={ 'broker': broker, 'app': app, 'organization': organization, 'user': get_user_context(user), 'old_card': old_card, 'new_card': new_card})
def pass_direct(request, charge=None, organization=None, strength=NORMAL): """ Returns True if the request authenticated ``User`` is a direct contributor (or manager) for the ``Organization`` associated to the request. Managers can issue all types of requests (GET, POST, etc.) while contributors are restricted to GET requests. .. image:: perms-contrib.* """ if charge: if not isinstance(charge, Charge): charge = get_object_or_404(Charge, processor_key=charge) organization = charge.customer elif organization: if not isinstance(organization, Organization): organization = get_object_or_404(Organization, slug=organization) else: organization = get_broker() return organization and _has_valid_access(request, [organization], strength)
def weekly_sales_report_notice(sender, provider, dates, data, **kwargs): recipients, bcc = _notified_recipients( provider, "weekly_sales_report_created") if SEND_EMAIL and recipients: prev_week, notused = dates #pylint:disable=unused-variable last_sunday = prev_week[-1] date = last_sunday.strftime("%A %b %d, %Y") app = get_current_app() site = get_current_site() # XXX using the provider in templates is incorrect. "Any questions # or comments..." should show DjaoDjin support email address. _send_notification_email(site, recipients, 'notification/weekly_sales_report_created.eml', bcc=bcc, context={'broker': get_broker(), 'provider': provider, # Without ``app`` we don't set the color correctly in # in notification/base.html, thus ending with an error # in premailer. 'app': app, 'table': data, 'date': date})
def pass_provider_only(request, charge=None, organization=None, strength=NORMAL): """ Returns True if the request authenticated ``User`` is a contributor (or manager) for a provider to the ``Organization`` associated to the request. When *strength* is NORMAL, managers can issue all types of requests (GET, POST, etc.) while contributors are restricted to GET requests. .. image:: perms-contrib-provider-only.* """ if charge: charge = get_object_or_404(Charge, processor_key=charge) organization = charge.customer elif organization: organization = get_object_or_404(Organization, slug=organization) if organization: return _has_valid_access(request, list(Organization.objects.providers_to(organization)), strength) return _has_valid_access(request, [get_broker()])
def user_reset_password_notice(sender, user, request, back_url, expiration_days, **kwargs): """ A user has reset her password. """ app = get_current_app() LOGGER.debug("[signal] user_reset_password_notice(user=%s, back_url=%s,"\ " expiration_days=%s)", user, back_url, expiration_days) if SEND_EMAIL: get_email_backend(connection=app.get_connection()).send( from_email=app.get_from_email(), recipients=[user.email], template='notification/password_reset.eml', context={ 'request': request, 'broker': get_broker(), 'app': app, 'back_url': back_url, 'expiration_days': expiration_days, 'user': get_user_context(user) })
def role_grant_accepted_notice(sender, role, grant_key, request=None, **kwargs): LOGGER.debug("[signal] role_grant_accepted_notice("\ " role=%s, grant_key=%s)", role, grant_key) originated_by = request.user if request else None user_context = get_user_context(originated_by) recipients, bcc = _notified_recipients( role.organization, "role_grant_accepted_notice", originated_by=originated_by) if SEND_EMAIL and recipients: site = get_current_site() app = get_current_app() _send_notification_email(site, recipients, 'notification/role_grant_accepted.eml', reply_to=user_context['email'], bcc=bcc, context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri(reverse('saas_role_detail', args=(role.organization, role.role_description))), 'organization': role.organization, 'role': role.role_description.title, 'user': user_context})
def subscribe_req_accepted_notice(sender, subscription, request_key, request=None, **kwargs): subscriber = subscription.organization recipients, bcc = _notified_recipients(subscriber, "subscribe_req_accepted_notice") LOGGER.debug("[signal] subscribe_req_accepted_notice("\ " subscription=%s, request_key=%s)", subscription, request_key) if SEND_EMAIL and recipients: site = get_current_site() app = get_current_app() user_context = get_user_context(request.user if request else None) _send_notification_email(site, recipients, 'notification/subscription_request_accepted.eml', reply_to=user_context['email'], bcc=bcc, context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri(reverse('organization_app', args=(subscriber,))), 'organization': subscriber, 'plan': subscription.plan, 'user': user_context})
def order_executed_notice(sender, invoiced_items, user, **kwargs): invoiced_items = list(invoiced_items) organization = (invoiced_items[0].dest_organization if invoiced_items else None) recipients, bcc = _notified_recipients(organization, 'order_executed') LOGGER.debug("[signal] order_executed_notice(invoiced_items=%s, user=%s)", [invoiced_item.pk for invoiced_item in invoiced_items], user) if SEND_EMAIL and recipients: broker = get_broker() broker_recipients, broker_bcc = _notified_recipients( broker, 'order_executed') app = get_current_app() site = get_current_site() context = { 'broker': broker, 'app': app, 'provider': broker, 'organization': organization, 'invoiced_items': invoiced_items, 'created_by': user } if user: context.update({ 'urls': { 'order': { 'created_by': reverse('users_profile', args=(user, )) } } }) kwargs = {} if broker.email and broker.email != site.get_from_email(): kwargs = {'reply_to': broker.email} get_email_backend(connection=site.get_email_connection()).send( from_email=site.get_from_email(), recipients=recipients, bcc=bcc + broker_recipients + broker_bcc, template='notification/order_executed.eml', context=context, **kwargs)
def subscribe_req_accepted_notice(sender, subscription, request_key, request=None, **kwargs): user_context = get_user_context(request.user if request else None) subscriber = subscription.organization if subscriber.email: site = get_current_site() app = get_current_app() LOGGER.debug("[signal] subscribe_req_accepted_notice("\ " subscription=%s, request_key=%s)", subscription, request_key) if SEND_EMAIL: get_email_backend(connection=app.get_connection()).send( from_email=app.get_from_email(), recipients=[subscriber.email], reply_to=user_context['email'], template='notification/subscription_request_accepted.eml', context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri( reverse('organization_app', args=(subscriber, ))), 'organization': subscriber, 'plan': subscription.plan, 'user': user_context }) else: LOGGER.warning( "%s will not be notified that its subscription to %s"\ " was accepted because e-mail address is invalid.", subscriber, subscription.plan)
def renewal_charge_failed_notice(sender, invoiced_items, total_price, final_notice, **kwargs): invoiced_items = list(invoiced_items) organization = (invoiced_items[0].dest_organization if invoiced_items else None) recipients, bcc = _notified_recipients(organization, 'renewal_charge_failed') LOGGER.debug("[signal] renewal_charge_failed_notice(invoiced_items=%s,"\ " total_price=%s, final_notice=%s)", [invoiced_item.pk for invoiced_item in invoiced_items], total_price, final_notice) if SEND_EMAIL and recipients: broker = get_broker() broker_recipients, broker_bcc = _notified_recipients( broker, 'renewal_charge_failed') app = get_current_app() site = get_current_site() context = { 'broker': broker, 'app': app, 'provider': broker, 'organization': organization, 'invoiced_items': invoiced_items, 'total_price': total_price, 'max_renewal_attempts': saas_settings.MAX_RENEWAL_ATTEMPTS, 'final_notice': final_notice, 'back_url': reverse('saas_organization_cart', args=(organization, )) } reply_to = None if broker.email and broker.email != site.get_from_email(): reply_to = broker.email _send_notification_email(site, recipients, 'notification/renewal_charge_failed.eml', reply_to=reply_to, bcc=bcc + broker_recipients + broker_bcc, context=context)
def processor_setup_error_notice(sender, provider, error_message, **kwargs): recipients, notused = _notified_recipients( provider, 'processor_setup_error') if SEND_EMAIL and recipients: broker = get_broker() site = get_current_site() app = get_current_app() broker_recipients, broker_bcc = _notified_recipients( broker, 'processor_setup_error') reply_to = None if broker.email and broker.email != site.get_from_email(): reply_to = broker.email _send_notification_email(site, recipients, 'notification/processor_setup_error.eml', reply_to=reply_to, bcc=broker_recipients + broker_bcc, context={ 'broker': broker, 'app': app, 'organization': provider, 'message': error_message, 'urls':{ 'update_bank': site.as_absolute_uri(reverse( 'saas_update_bank', args=(provider,))), }})
def order_executed_notice(sender, invoiced_items, user, **kwargs): from saas.models import Transaction invoiced_items = Transaction.objects.filter(id__in=invoiced_items) broker = get_broker() recipients, bcc = _notified_recipients( invoiced_items.first().dest_organization) broker_recipients, broker_bcc = _notified_recipients(broker) app = get_current_app() LOGGER.debug("[signal] order_executed_notice(invoiced_items=%s, user=%s)", invoiced_items, user) if SEND_EMAIL: get_email_backend(connection=app.get_connection()).send( from_email=app.get_from_email(), recipients=recipients, bcc=bcc + broker_recipients + broker_bcc, reply_to=broker_recipients[0], template='notification/order_executed.eml', context={ 'broker': broker, 'app': app, 'provider': broker, 'invoiced_items': invoiced_items })
def get_initial(self): """ Populates place order forms with the organization address whenever possible. """ self.customer = self.get_organization() kwargs = super(CardFormMixin, self).get_initial() provider = get_broker() if self.customer.country: country = self.customer.country else: country = provider.country if self.customer.region: region = self.customer.region else: region = provider.region kwargs.update({'card_name': self.customer.full_name, 'card_city': self.customer.locality, 'card_address_line1': self.customer.street_address, 'country': country, 'region': region, 'card_address_zip': self.customer.postal_code}) return kwargs
def subscribe_grant_accepted_notice(sender, subscription, grant_key, request=None, **kwargs): provider = subscription.plan.organization originated_by = request.user if request else None recipients, bcc = _notified_recipients(provider, "subscribe_grant_accepted_notice", originated_by=originated_by) LOGGER.debug("[signal] subscribe_grant_accepted_notice("\ " subscription=%s, grant_key=%s)", subscription, grant_key) if SEND_EMAIL and recipients: site = get_current_site() app = get_current_app() user_context = get_user_context(originated_by) get_email_backend(connection=site.get_email_connection()).send( from_email=site.get_from_email(), recipients=recipients, bcc=bcc, reply_to=user_context['email'], template='notification/subscription_grant_accepted.eml', context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri( reverse('organization_app', args=(provider, ))), 'organization': subscription.organization, 'plan': subscription.plan, 'user': user_context })
def user_relation_requested_notice(sender, organization, user, reason=None, **kwargs): if user.email != organization.email: if user.email: site = get_current_site() app = get_current_app() LOGGER.debug("[signal] user_relation_requested_notice("\ "organization=%s, user=%s, reason=%s)", organization, user, reason) if SEND_EMAIL: get_email_backend(connection=app.get_connection()).send( from_email=app.get_from_email(), recipients=[organization.email], reply_to=user.email, template='notification/user_relation_requested.eml', context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri( reverse('saas_role_list', args=(organization, ))), 'organization': organization, 'reason': reason if reason is not None else "", 'user': get_user_context(user) }) else: LOGGER.warning( "%s will not be notified of role request to %s"\ "because e-mail address is invalid.", user, organization)
def user_registered_notice(sender, user, **kwargs): """ A new user has registered (frictionless or completely) """ LOGGER.debug("[signal] user_registered_notice(user=%s)", user) if not SEND_EMAIL: return broker = get_broker() app = get_current_app() site = get_current_site() recipients, bcc = _notified_recipients(broker, "user_registered_notice") if hasattr(app, 'welcome_email') and app.welcome_email: back_url = site.as_absolute_uri() reply_to = None if broker.email and broker.email != site.get_from_email(): reply_to = broker.email _send_notification_email(site, [user.email], 'notification/user_welcome.eml', reply_to=reply_to, bcc=recipients + bcc, context={ 'broker': broker, 'app': app, 'user': get_user_context(user), 'back_url': back_url }) if recipients: _send_notification_email(site, recipients, 'notification/user_registered.eml', bcc=bcc, context={ 'broker': broker, 'app': app, 'user': get_user_context(user) })
def handle(self, *args, **options): #pylint: disable=too-many-locals,too-many-statements from saas.metrics.base import month_periods # avoid import loop RazorpayBackend.bypass_api = True now = datetime.datetime.utcnow().replace(tzinfo=utc) from_date = now from_date = datetime.datetime(year=from_date.year, month=from_date.month, day=1) if args: from_date = datetime.datetime.strptime(args[0], '%Y-%m-%d') # Create a set of 3 plans broker = get_broker() plan, _ = Plan.objects.get_or_create(slug='basic', defaults={ 'title': "Basic", 'description': "Basic Plan", 'period_amount': 24900, 'broker_fee_percent': 0, 'period_type': 4, 'organization': broker, 'is_active': True }) advance_discount = AdvanceDiscount.objects.get_or_create( plan=plan, discount_type=AdvanceDiscount.PERCENTAGE, amount=1000, length=12) Plan.objects.get_or_create(slug='medium', defaults={ 'title': "Medium", 'description': "Medium Plan", 'period_amount': 24900, 'broker_fee_percent': 0, 'period_type': 4, 'organization': broker, 'is_active': True }) plan, _ = Plan.objects.get_or_create(slug='premium', defaults={ 'title': "Premium", 'description': "Premium Plan", 'period_amount': 18900, 'broker_fee_percent': 0, 'period_type': 4, 'organization': broker, 'is_active': True }) advance_discount = AdvanceDiscount.objects.get_or_create( plan=plan, discount_type=AdvanceDiscount.PERCENTAGE, amount=81, length=12) # Create Income transactions that represents a growing bussiness. provider = Organization.objects.get(slug=options['provider']) processor = Organization.objects.get(pk=PROCESSOR_ID) for end_period in month_periods(from_date=from_date): nb_new_customers = random.randint(0, 9) for _ in range(nb_new_customers): queryset = Plan.objects.filter(organization=provider, period_amount__gt=0) plan = queryset[random.randint(0, queryset.count() - 1)] created = False trials = 0 while not created: try: first_name = self.FIRST_NAMES[random.randint( 0, len(self.FIRST_NAMES) - 1)] last_name = self.LAST_NAMES[random.randint( 0, len(self.LAST_NAMES) - 1)] full_name = '%s %s' % (first_name, last_name) slug = slugify('demo%d' % random.randint(1, 1000)) customer, created = Organization.objects.get_or_create( slug=slug, full_name=full_name) #pylint: disable=catching-non-exception except IntegrityError: trials = trials + 1 if trials > 10: raise RuntimeError( 'impossible to create a new customer after 10 trials.' ) Organization.objects.filter(pk=customer.id).update( created_at=end_period) subscription = Subscription.objects.create( organization=customer, plan=plan, ends_at=now + datetime.timedelta(days=31)) Subscription.objects.filter(pk=subscription.id).update( created_at=end_period) # Insert some churn in % churn_rate = 2 all_subscriptions = Subscription.objects.filter( plan__organization=provider) nb_churn_customers = (all_subscriptions.count() * churn_rate // 100) subscriptions = random.sample( list(all_subscriptions), all_subscriptions.count() - nb_churn_customers) for subscription in subscriptions: nb_periods = random.randint(1, 6) amount = nb_periods * subscription.plan.period_amount ends_at = subscription.plan.end_of_period( subscription.ends_at, nb_periods) transaction_item = Transaction.objects.new_subscription_order( subscription, amount=amount, descr=humanize.describe_buy_periods( subscription.plan, ends_at, nb_periods), created_at=end_period) if transaction_item.dest_amount < 50: continue transaction_item.orig_amount = transaction_item.dest_amount transaction_item.orig_unit = transaction_item.dest_unit transaction_item.save() charge = Charge.objects.create( created_at=transaction_item.created_at, amount=transaction_item.dest_amount, customer=subscription.organization, description='Charge for %d periods' % nb_periods, last4=1241, exp_date=datetime_or_now(), processor=processor, processor_key=str(transaction_item.pk), # XXX We can't do that yet because of # ``PROCESSOR_BACKEND.charge_distribution(self)`` # unit=transaction_item.dest_unit, state=Charge.CREATED) charge.created_at = transaction_item.created_at charge.save() ChargeItem.objects.create(invoiced=transaction_item, charge=charge) charge.payment_successful() churned = all_subscriptions.exclude( pk__in=[subscription.pk for subscription in subscriptions]) for subscription in churned: subscription.ends_at = end_period subscription.save() self.stdout.write( "%d new and %d churned customers at %s" % (nb_new_customers, nb_churn_customers, end_period))
def get_provider(): return get_broker()
def get_template_names(self): if not fail_direct(self.request, organization=get_broker()): return ['app_proxy_help.html'] return super(DjaoAppPageView, self).get_template_names()
def get_context_data(self, **kwargs): context = super(NotificationListView, self).get_context_data(**kwargs) broker = get_broker() context.update({ 'notifications': { 'card_updated': { 'title': _("Card updated"), 'descr': _("This notification is sent when a credit card"\ " on file is updated.") }, 'charge_receipt': { 'title': _("Charge receipt"), 'descr': _("This notification is sent when a charge is"\ " created on a credit card. It is also sent when the charge is refunded.") }, 'claim_code_generated': { 'title': _("Claim code"), 'descr': _("") }, 'expires_soon': { 'title': _("Expires soon"), 'descr': _("This notification is sent when a subscription"\ " is about to expire.") }, 'order_executed': { 'title': _("Order confirmation"), 'descr': _("This notification is sent when an order has"\ " been confirmed but a charge has been successfuly processed yet.") }, 'organization_updated': { 'title': _("Profile updated"), 'descr': _("This notification is sent when a profile"\ " is updated.") }, 'password_reset': { 'title': _("Password reset"), 'descr': _("This notification is sent to a user that has"\ " requested to reset their password through a \"forgot password?\" link.") }, 'user_activated': { 'title': _("User activated"), 'descr': _("This notification is sent to profile managers"\ " of a domain when a user has activated his/her account.") }, 'user_contact': { 'title': _("User contact"), 'descr': _("") }, 'user_registered': { 'title': _("User registered"), 'descr': _("This notification is sent to profile managers"\ " of a domain when a user has registered.") }, 'user_relation_requested': { 'title': _("User relation requested"), 'descr': _("This notification is sent to profile managers"\ " of an organization when a user has requested a role on that organization.") }, 'verification': { 'title': _("Verification"), 'descr': _("This notification is sent to verify an e-mail"\ " address of a user.") }, 'sales_report': { 'title': _("Weekly sales report"), 'descr': _("This notification is sent to profile managers."\ " It contains the weekly sales results.") }, }, 'role_descriptions': broker.get_role_descriptions() }) self.update_context_urls( context, {'send_test_email': reverse('api_notification_base')}) return context
def get_site(obj): #pylint:disable=unused-argument broker = get_broker() return {'printable_name': broker.printable_name, 'email': broker.email}
def get_test_email_context(): broker = get_broker() site = get_current_site() return { # specific to charge_receipt 'charge': { 'price': Price(2999, 'usd'), 'processor_key': "{{charge.processor_key}}", 'last4': "{{charge.last4}}", 'exp_date': "{{charge.exp_date}}", 'created_by': {}, }, 'email_by': { 'username': "******", 'email': "{{charge.email_by.email}}", 'first_name': "{{charge.email_by.first_name}}", 'printable_name': "{{charge.email_by.printable_name}}" }, # specific to organization_updated 'changes': {}, # specific to claim_code_generated 'subscriber': {}, # specific to card_updated 'old_card': { 'last4': "{{old_card.last4}}", 'exp_date': "{{old_card.exp_date}}" }, 'new_card': { 'last4': "{{new_card.last4}}", 'exp_date': "{{new_card.exp_date}}" }, # specific to weekly_report 'table': {}, 'date': '', # app_created/app_updated 'instance': { 'printable_name': "{{instance.printable_name}}" }, # common across all notifications 'urls': { 'cart': site.as_absolute_uri(reverse('saas_cart')), 'user': { 'profile': None }, 'organization': { 'profile': None } }, 'user': { 'username': "******", 'email': "{{user.email}}", 'first_name': "{{user.first_name}}", 'printable_name': "{{user.printable_name}}" }, 'organization': { 'printable_name': "{{organization.printable_name}}" }, 'site': site, 'app': get_current_app(), 'provider': broker, 'broker': broker }
def subscribe_grant_created_notice(sender, subscription, reason=None, invite=False, request=None, **kwargs): #pylint:disable=too-many-locals if subscription.grant_key: user_context = get_user_context(request.user if request else None) organization = subscription.organization back_url_base = reverse('subscription_grant_accept', args=( organization, subscription.grant_key, )) LOGGER.debug("[signal] subscribe_grant_created_notice("\ " subscription=%s, reason=%s, invite=%s)", subscription, reason, invite) # We don't use `_notified_recipients` because # 1. We need the actual User object to update/create a Contact # 2. We should not send to the organization e-mail address # because the e-mail there might not be linked to a manager. managers = organization.with_role(saas_settings.MANAGER) emails = kwargs.get('emails', None) if emails: managers = managers.filter(email__in=emails) if not managers: LOGGER.warning( "%s will not be notified of a subscription grant to %s"\ " because there are no managers to send e-mails to.", organization, subscription.plan) for manager in managers: # The following line could as well be `if invite:` if has_invalid_password(manager): # The User is already in the system but the account # has never been activated. #pylint:disable=unused-variable contact, notused = Contact.objects.update_or_create_token( manager) back_url = "%s?next=%s" % (reverse( 'registration_activate', args=(contact.verification_key, )), back_url_base) else: back_url = back_url_base LOGGER.debug("[signal] would send subscribe_grant_created_notice"\ " for subscription '%s' to '%s'", subscription, manager.email) if SEND_EMAIL: site = get_current_site() app = get_current_app() _send_notification_email( site, [manager.email], 'notification/subscription_grant_created.eml', reply_to=user_context['email'], context={ 'broker': get_broker(), 'app': app, 'back_url': site.as_absolute_uri(back_url), 'organization': organization, 'plan': subscription.plan, 'reason': reason if reason is not None else "", 'invite': invite, 'user': user_context })
def on_user_post_save(sender, instance, created, raw, **kwargs): #pylint:disable=unused-argument if created and instance.is_superuser: get_broker().add_manager(instance)
def is_direct(request, organization=None): if organization is None: organization = get_broker() return pass_direct(request, organization=organization)
def inject_edition_tools(response, request, context=None, body_top_template_name=None, body_bottom_template_name=None): """ If the ``request.user`` has editable permissions, this method injects the edition tools into the html *content* and return a BeautifulSoup object of the resulting content + tools. If the response is editable according to the proxy rules, this method returns a BeautifulSoup object of the content such that ``PageMixin`` inserts the edited page elements. """ #pylint:disable=too-many-locals,too-many-nested-blocks,too-many-statements content_type = response.get('content-type', '') if not content_type.startswith('text/html'): return None if not is_authenticated(request): return None if context is None: context = {} # ``app.account`` is guarenteed to be in the same database as ``app``. # ``site.account`` is always in the *default* database, which is not # the expected database ``Organization`` are typically queried from. app = get_current_app() provider = app.account soup = None if app.show_edit_tools and get_role_model().objects.valid_for( organization=provider, user=request.user): edit_urls = { 'api_medias': reverse('uploaded_media_elements', kwargs={'path': ''}), 'api_sitecss': reverse('edit_sitecss'), 'api_less_overrides': reverse('pages_api_less_overrides'), 'api_sources': reverse('pages_api_sources'), 'api_page_element_base': reverse('api_page_element', kwargs={'path': ''}), 'api_plans': reverse('saas_api_plans', args=(provider, )), 'plan_update_base': reverse('saas_plan_base', args=(provider, )) } try: # The following statement will raise an Exception # when we are dealing with a ``FileSystemStorage``. _ = get_storage_class().bucket_name edit_urls.update( {'media_upload': reverse('api_credentials_organization')}) except AttributeError: LOGGER.debug("doesn't look like we have a S3Storage.") # XXX sites which are hosted on a same domain shouldn't disable # all edit functionality, just the edition of base templates. site = get_current_site() enable_code_editor = is_domain_site(site) if enable_code_editor: dj_urls = djaoapp_urls(request, account=provider, base=site.as_base()) body_bottom_template_name = "pages/_body_bottom_edit_tools.html" else: dj_urls = djaoapp_urls(request, account=provider) body_bottom_template_name = "pages/_body_bottom.html" context.update({ 'ENABLE_CODE_EDITOR': enable_code_editor, 'FEATURE_DEBUG': settings.FEATURES_DEBUG, 'urls': { 'djaodjin': dj_urls, 'edit': edit_urls } }) context.update(csrf(request)) soup = pages_inject_edition_tools( response, request, context=context, body_top_template_name=body_top_template_name, body_bottom_template_name=body_bottom_template_name) # Insert the authenticated user information and roles on organization. if not soup: soup = BeautifulSoup(response.content, 'html5lib') if soup and soup.body: # Implementation Note: we have to use ``.body.next`` here # because html5lib "fixes" our HTML by adding missing # html/body tags. Furthermore if we use #``soup.body.insert(1, BeautifulSoup(body_top, 'html.parser'))`` # instead, later on ``soup.find_all(class_=...)`` returns # an empty set though ``soup.prettify()`` outputs the full # expected HTML text. auth_user = soup.body.find(class_='header-menubar') user_menu_template = '_menubar.html' if auth_user and user_menu_template: serializer_class = import_string(rules_settings.SESSION_SERIALIZER) serializer = serializer_class(request) path_parts = reversed(request.path.split('/')) top_accessibles = [] has_broker_role = False active_organization = None for role, organizations in six.iteritems(serializer.data['roles']): for organization in organizations: if organization['slug'] == request.user.username: # Personal Organization continue db_obj = get_organization_model().objects.get( slug=organization['slug']) # XXX Remove query. if db_obj.is_provider: settings_location = reverse( 'saas_dashboard', args=(organization['slug'], )) else: settings_location = reverse( 'saas_organization_profile', args=(organization['slug'], )) app_location = reverse('organization_app', args=(organization['slug'], )) if organization['slug'] in path_parts: active_organization = TopAccessibleOrganization( organization['slug'], organization['printable_name'], settings_location, role, app_location) if is_broker(organization['slug']): has_broker_role = True top_accessibles += [ TopAccessibleOrganization( organization['slug'], organization['printable_name'], settings_location, role, app_location) ] if not active_organization and has_broker_role: active_organization = get_broker() context.update({'active_organization': active_organization}) context.update({'top_accessibles': top_accessibles}) template = loader.get_template(user_menu_template) user_menu = render_template(template, context, request).strip() auth_user.clear() els = BeautifulSoup(user_menu, 'html5lib').body.ul.children for elem in els: auth_user.append(BeautifulSoup(str(elem), 'html5lib')) return soup
def get_notifications(user=None): broker = get_broker() notifications = { 'card_updated': { 'title': _("Card updated"), 'descr': _("This notification is sent when a credit card"\ " on file is updated.") }, 'charge_receipt': { 'title': _("Charge receipt"), 'descr': _("This notification is sent when a charge is"\ " created on a credit card. It is also sent when the charge is refunded.") }, 'claim_code_generated': { 'title': _("Claim code"), 'descr': _("This notification is sent to the user invited"\ " through a groupBuy.") }, 'expires_soon': { 'title': _("Expires soon"), 'descr': _("This notification is sent when a subscription"\ " is about to expire.") }, 'order_executed': { 'title': _("Order confirmation"), 'descr': _("This notification is sent when an order has"\ " been confirmed but a charge has not been successfully processed yet.") }, 'organization_updated': { 'title': _("Profile updated"), 'descr': _("This notification is sent when a profile"\ " is updated.") }, 'password_reset': { 'title': _("Password reset"), 'descr': _("This notification is sent to a user that has"\ " requested to reset their password through a \"forgot password?\" link.") }, 'user_activated': { 'title': _("User activated"), 'descr': _("This notification is sent to profile managers"\ " of a domain when a user has activated his/her account.") }, 'user_contact': { 'title': _("User contact"), 'descr': _("This notification is sent to profile managers"\ " of a domain when a user submits an inquiry on the contact-us page.") }, 'user_registered': { 'title': _("User registered"), 'descr': _("This notification is sent to profile managers"\ " of a domain when a user has registered.") }, 'user_welcome': { 'title': _("Welcome e-mail"), 'descr': _("This notification is sent to a user after they"\ " register an account with the site."), }, 'role_request_created': { 'title': _("Role requested"), 'descr': _("This notification is sent to profile managers"\ " of an organization when a user has requested a role on that organization.") }, 'verification': { 'title': _("Verification"), 'descr': _("This notification is sent to verify an e-mail"\ " address of a user.") }, 'sales_report': { 'title': _("Weekly sales report"), 'descr': _("This notification is sent to profile managers."\ " It contains the weekly sales results.") }, } for role_descr in broker.get_role_descriptions(): notifications.update({ "%s_role_grant_created" % role_descr.slug: { 'title': _("%(role_title)s Added") % { 'role_title': role_descr.title }, 'descr': "" } }) # user with profile manager of broker (or theme editor) if not user or broker.with_role( saas_settings.MANAGER).filter(pk=user.pk).exists(): return notifications # regular subscriber return { key: notifications[key] for key in [ 'charge_receipt', 'card_updated', 'order_executed', 'organization_updated', 'expires_soon' ] }