Example #1
0
def start_subscription(user):
    if not user.payment:
        raise APIError(
            "Cannot start subscription for user without a credit card: %s" %
            user.id)

    user.payment.start()
    Session.commit()
Example #2
0
def delete(user_id):
    # TODO: user_id -> user
    u = model.User.get(user_id)
    if not u:
        raise APIError('Invalid user: %s' % user_id)

    delete_payments(u)
    u.delete()
    Session.commit()
Example #3
0
def delete_payments(user):
    user.time_next_payment = None
    if not user.num_remaining:
        user.num_remaining = 0

    is_free_plan = user.plan and not user.plan.price and not user.plan.features.get(
        'num_emails')
    if is_free_plan:
        user.num_remaining = None

    if user.payment:
        user.payment.delete()

    Session.commit()
Example #4
0
def get_user(request, required=False, joinedload=None):
    """
    Get the current logged in User object, else None.

    Overrides request.features from loaded user.
    """
    user_id = get_user_id(request, required=required)
    if not user_id:
        return

    q = Session.query(model.User)
    for p in iterate(joinedload or []):
        q = q.options(orm.joinedload(p))

    u = q.get(user_id)
    if not u:
        request.session.pop('user_id', None)
        request.session.save()
        return get_user(request, required=required)  # Try again.

    if u:
        # Override features
        request.features.update(u.config or {})

    return u
Example #5
0
    def index(self):
        api.account.get_admin(self.request)
        q = Session.query(model.User)
        q = q.options(orm.joinedload_all('accounts.reports'),
                      orm.joinedload_all('subscriptions'))
        q = q.order_by(model.User.id.asc())
        users = q.all()

        self.c.active_users, self.c.inactive_users, self.c.active_trials = [], [], []
        for u in users:
            account_reports = [a.reports for a in u.accounts]
            if u.is_active and (u.subscriptions or account_reports
                                or u.payment):
                self.c.active_users.append(u)
                if u.plan_id == 'trial':
                    self.c.active_trials.append(u)
            else:
                self.c.inactive_users.append(u)

        payment_info = [u for u in users if u.payment]
        active_customers = [
            u for u in payment_info
            if u.payment.is_charging and u.num_remaining is None
        ]
        self.c.num_users = len(users)
        self.c.num_payment_info = len(payment_info)
        self.c.num_active_customers = len(active_customers)
        self.c.num_mrr = sum(
            (u.plan.price_monthly or 0) for u in active_customers)

        self.c.by_plan = groupby_count(active_customers,
                                       key=lambda u: u.plan_id)
        self.c.by_payment = groupby_count(payment_info,
                                          key=lambda u: u.payment.id)

        self.c.expiring_trials = []
        for u in self.c.active_trials:
            num_reports = len([a.reports for a in u.accounts])
            if num_reports * 2 < u.num_remaining:
                continue
            self.c.expiring_trials.append(u)

        q = Session.query(model.ReportLog).order_by(
            model.ReportLog.id.desc()).limit(10)
        self.c.recent_reports = q.all()

        return self._render('admin/index.mako')
Example #6
0
def set_plan(user, plan_id, update_subscription=None):
    plan = pricing.PLANS_LOOKUP.get(plan_id)
    if not plan:
        raise APIError('Invalid plan: %s' % plan_id)

    user.plan_id = plan_id
    num_remaining = plan.features.get('num_emails')
    if num_remaining or not user.num_remaining:
        user.num_remaining = num_remaining

    Session.commit()

    if update_subscription is None:
        # Default behaviour
        update_subscription = user.num_remaining is None or user.num_remaining <= 0

    if update_subscription and user.payment:
        user.payment.start()
Example #7
0
def get_or_create(user_id=None,
                  email=None,
                  service='google',
                  token=None,
                  display_name=None,
                  plan_id=None,
                  remote_id=None,
                  remote_data=None,
                  **create_kw):
    u = None
    q = Session.query(model.User).options(orm.joinedload(model.User.accounts))

    if user_id:
        u = q.get(user_id)
        if not u:
            raise APIError('Invalid user: %s' % user_id)

    elif email:
        u = q.filter(model.User.email == email).first()

    if not u:
        u = model.User.create(email=email,
                              display_name=display_name,
                              **create_kw)
        set_plan(u, plan_id or 'trial')

    if service:
        # Create account
        account = u.get_account(service=service)
        if not account:
            account = model.Account.create(display_name=display_name,
                                           user=u,
                                           service=service,
                                           remote_id=remote_id,
                                           remote_data=remote_data)
            u.accounts.append(account)

        if token and token.get('refresh_token'):
            # Update token if it's a better one (with refresh).
            account.oauth_token = token

    Session.commit()
    return u
Example #8
0
def set_payments(user,
                 plan_id=None,
                 card_token=None,
                 metadata=None,
                 payment_type='stripe'):
    if plan_id:
        try:
            set_plan(user, plan_id)
        except KeyError:
            raise APIError('Invalid plan: %s' % plan_id)

    p = user.payment
    if p and p.id != payment_type:
        raise APIError('Incompatible payment type user: %s' % user)

    if not p:
        p = payment.registry[payment_type](user)

    if p.id == 'stripe' and not card_token:  # For testing
        log.warning('Skipping interfacing set_payments for user: %s' % user)
        Session.commit()
        return user

    p.set(card_token, metadata=metadata)
    Session.commit()

    if plan_id and not user.num_remaining:
        user.payment.start()
        Session.commit()

    return user
Example #9
0
    def user(self):
        u = api.account.get_admin(self.request)

        user_id = self.request.matchdict['id']
        q = Session.query(model.User)
        q = q.options(
            orm.joinedload_all('accounts.reports.subscriptions.user'))
        self.c.user = q.get(user_id)

        q = Session.query(model.User).filter_by(invited_by_user_id=user_id)
        q = q.options(orm.joinedload_all('subscriptions'))
        self.c.invited = q.all()

        self.c.invited_by = None
        if self.c.user.invited_by_user_id:
            self.c.invited_by = model.User.get(self.c.user.invited_by_user_id)

        q = Session.query(model.ReportLog).join(
            model.Account).filter_by(user_id=self.c.user.id)
        q = q.order_by(model.ReportLog.id.desc()).limit(10)
        self.c.recent_reports = q.all()

        return self._render('admin/user.mako')
Example #10
0
def get(id=None, email=None, token=None):
    if not any([id, email, token]):
        raise APIError('Must specify user query criteria.')

    q = Session.query(model.User)

    if id:
        q = q.filter_by(id=id)

    if email:
        q = q.filter_by(email=email)

    if token:
        email_token, id = token.split('-', 2)
        q = q.filter_by(id=int(id), email_token=email_token)

    return q.first()
Example #11
0
def close_session(*args, **kwargs):
    from briefmetrics.model.meta import Session
    Session.remove()
Example #12
0
def connect_oauth(request, oauth, user_required=False):
    user, account = get_account(request,
                                service=oauth.id,
                                user_required=user_required)

    code = request.params.get('code')
    if not code:
        raise httpexceptions.HTTPBadRequest('Missing code.')

    error = request.params.get('error')
    if error:
        raise APIError('Failed to connect: %s' % error)

    url = request.current_route_url().replace(
        'http://', 'https://')  # We lie, because honeybadger.

    try:
        token = oauth.auth_token(url)
    except InvalidGrantError:
        # Try again.
        raise httpexceptions.HTTPSeeOther(
            request.route_path('account_login', service=oauth.id))
    except OAuth2Error as e:
        raise APIError(
            "Unexpected authentication error, please try again: %s" %
            e.description)
    except ValueError as e:
        raise APIError("Unexpected response error, please try again: %s" % e)

    remote_id, email, display_name, remote_data = oauth.query_user()
    if not user:
        # New user
        user = get_or_create(
            email=email,
            service=oauth.id,
            token=token,
            display_name=display_name,
            remote_id=remote_id,
            remote_data=remote_data,
        )
        account = user.accounts[0]
    elif not account:
        # New account
        account = model.Account.create(
            display_name=display_name or user.display_name,
            user=user,
            oauth_token=token,
            service=oauth.id,
            remote_id=remote_id,
            remote_data=remote_data,
        )
    else:
        # Update account
        account.oauth_token = token
        account.remote_id = remote_id
        account.remote_data = remote_data
        force_skip = oauth.is_autocreate and Session.query(
            model.Report).filter_by(account_id=account.id).limit(1).count()
        if force_skip:
            # Already exists, skip autocreate.
            oauth.is_autocreate = False

    Session.commit()

    return account