Exemple #1
0
    def users(self):
        """
        Use pagination to list out users in the database
        """
        page = request.args.get('page', 1)
        page_size = request.args.get('page_size', 30)

        # return 30 users at a time max
        if page_size > 30:
            page_size = 30

        sort_by = User.sort_by(request.args.get('sort', 'created_on'),
                               request.args.get('direction', 'desc'))
        order_values = '{0} {1}'.format(sort_by[0], sort_by[1])

        # a search feature is provided if the client wants to implement one
        # thats what request.args.get('q') is
        paginated_users = User.query \
            .filter(User.search(request.args.get('q', text('')))) \
            .order_by(User.role.asc(), User.payment_id, text(order_values)) \
            .paginate(page, page_size, True)

        dumped_users = users_schema.dump(paginated_users.items)
        response = {
            'data': {
                'users': dumped_users,
                'has_next': paginated_users.has_next,
                'has_prev': paginated_users.has_prev,
                'prev_num': paginated_users.prev_num,
                'next_num': paginated_users.next_num,
            }
        }
        return response
Exemple #2
0
def users(db):
    """
    Create user fixtures. They reset per test.

    :param db: Pytest fixture
    :return: SQLAlchemy database session
    """
    # db.session.query(User).delete()

    users = [
        {
            'role': 'admin',
            'email': '*****@*****.**',
            'username': '******',
            'password': '******'
        },
        {
            'email': '*****@*****.**',
            'username': '******',
            'password': '******'
        }
    ]

    for user in users:
        exists = User.find_by_identity(user['username'])
        if exists:
            exists.delete()
        db.session.add(User(**user))

    db.session.commit()

    return db
    def post(self):
        json_data = request.get_json()

        if not json_data:
            response = {'error': 'Invalid input.'}
            return response, 400

        try:
            data = registration_schema.load(json_data)
        except ValidationError as err:
            response = {'error': err.messages}
            return response, 422

        user = User()
        user.email = data.get('email')
        user.username = data.get('username')
        user.password = User.encrypt_password(data.get('password'))
        user.save()

        # send verification email with celery as a background task
        User.init_verify_email(user.email)

        message = ('Please check the email you registered with for a'
                   ' verification email.')
        response = {'data': {'created': True, 'message': message}}
        headers = {'Location': url_for('AuthView:post')}
        return response, 201, headers
Exemple #4
0
def subscriptions(db):
    """
    Create subscription fixutres.

    :param db: Pytest fixture
    :return: SQLAlchemy database session
    """
    subscriber = User.find_by_identity('*****@*****.**')
    if subscriber:
        subscriber.delete()
    db.session.query(Subscription).delete()

    params = {
        'role': 'member',
        'email': '*****@*****.**',
        'username': '******',
        'name': 'Subby',
        'payment_id': 'cus_000',
        'password': '******',
        'active': True
    }

    subscriber = User(**params)
    # User needs to be commited to be able to assign a subscription to it
    db.session.add(subscriber)
    db.session.commit()

    # Create a subscription
    params = {
        'user_id': subscriber.id,
        'plan': 'gold'
    }
    subscription = Subscription(**params)
    db.session.add(subscription)

    # Create the users CC
    params = {
        'user_id': subscriber.id,
        'brand': 'Visa',
        'last4': '4242',
        'exp_date': datetime.date(2019, 6, 1)
    }
    credit_card = CreditCard(**params)
    db.session.add(credit_card)

    db.session.commit()

    return db
Exemple #5
0
 def test_deserialize_token_tampered(self, token):
     """
     User.deserialize_token returns None if a token has been tampered with
     """
     tampered_token = 'hacked!!{0}'.format(token)
     user = User.deserialize_token(tampered_token)
     assert user is None
Exemple #6
0
    def delete_users(self):
        """Option to bulk delete or delete a single user"""
        json_data = request.get_json()
        if not json_data:
            response = {'error': 'Invalid input.'}
            return response, 400

        try:
            data = bulk_delete_schema.load(json_data)
        except ValidationError as err:
            response = {'error': err.messages}
            return response, 422

        ids = User.get_bulk_action_ids(scope=data['scope'],
                                       ids=data['bulk_ids'],
                                       omit_ids=[current_user.id],
                                       query=request.args.get('q', text('')))

        # use a celery task to do this in the background
        from vidme.blueprints.admin.tasks import delete_users
        delete_users.delay(ids)

        response = {
            'data': {
                'deleted':
                True,
                'message':
                '{0} user(s) were scheduled to be deleted.'.format(len(ids))
            }
        }
        return response
Exemple #7
0
    def get_user(self, username):
        """Allows an admin to fetch specific user data
        """
        user = User.find_by_identity(username)

        if user is None:
            response = {'error': USER_NOT_FOUND}
            return response, 404

        invoices = Invoice.billing_history(user=user)
        if user.subscription:
            # get the upcoming invoice from Stripe
            upcoming = Invoice.upcoming(customer_id=user.payment_id)
        else:
            upcoming = None

        dumped_user = user_detail_schema.dump(user)
        dumped_invoices = invoices_schema.dump(invoices)
        response = {
            'data': {
                'user': dumped_user,
                'invoices': dumped_invoices,
                'upcoming_invoice': upcoming
            }
        }
        return response
Exemple #8
0
def db(app):
    """
    Set up test database, this only gets executed once per session.

    :param app: Pytest fixture
    :return: SQLAlchemy database session
    """

    _db.drop_all()
    _db.create_all()

    # Create a single user, a lot of tests will not mutate this user
    params = {
        'role': 'admin',
        'email': '*****@*****.**',
        'username': '******',
        'password': '******',
        'active': True
    }

    admin = User(**params)

    _db.session.add(admin)
    _db.session.commit()

    return _db
Exemple #9
0
    def edit_user(self, username):
        """
        Admins can edit user accounts, for example if the username is
        offensive/goes against guidelines or update their permissions
        """
        # find the User
        user = User.find_by_identity(username)

        if user is None:
            response = {'error': USER_NOT_FOUND}
            return response, 404

        # load the json data
        json_data = request.get_json()

        # check for errors
        if not json_data:
            response = {'error': 'Invalid input.'}
            return response, 400

        try:
            data = admin_edit_user_schema.load(json_data)
        except ValidationError as err:
            response = {'error': err.messages}
            return response, 422

        # check if user is the last admin
        if User.is_last_admin(user, data['role']):
            response = {'error': 'User is the last admin in the system.'}
            return response, 400

        # is username being changed
        if user.username != data['username']:
            existing_username = User.find_by_identity(data['username'])
            if existing_username is None:
                user.username = data['username']
            else:
                response = {'error': 'Username is already taken.'}
                return response, 400

        user.role = data['role']
        user.save()

        headers = {
            'Location': url_for('AdminView:get_user', username=user.username)
        }
        return '', 204, headers
    def test_deliver_verification_email(self, token):
        """Successfully deliver a verification email"""
        with mail.record_messages() as outbox:
            user = User.find_by_identity('*****@*****.**')
            deliver_verification_email(user.id, token)

            assert len(outbox) == 1
            assert token in outbox[0].body
Exemple #11
0
def token(db):
    """
    Serialize a JWS token.

    :param db: Pytest fixture
    :return: JWS token
    """
    user = User.find_by_identity('*****@*****.**')
    return user.serialize_token()
Exemple #12
0
def delete_users(ids):
    """
    Delete users and potentially cancel their subscription.

    :param ids: List of ids to be deleted
    :type ids: list
    :return: int
    """
    return User.bulk_delete(ids)
Exemple #13
0
def ensure_unique_identity(data):
    """
    Ensures that an email and/or username is not already taken

    :return: data from the request
    """
    user = User.find_by_identity(data)

    if user:
        raise ValidationError('{0} already exists.'.format(data))

    return data
Exemple #14
0
    def test_edit_user(self, subscriptions):
        """Successfully update a user account and set location headers"""
        self.authenticate()
        data = {'role': 'admin', 'username': '******'}
        response = self.client.put(url_for('AdminView:edit_user',
                                           username='******'),
                                   json=data)
        location = response.headers['Location']
        assert response.status_code == 204
        assert location == url_for('AdminView:get_user', username='******')

        user = User.find_by_identity('firstSub1')
        assert user.role == 'admin'
Exemple #15
0
    def test_cancel_subscription(self, subscriptions, mock_stripe):
        """Successfully cancel a user's subscription"""
        self.authenticate()
        response = self.client.delete(
            url_for('AdminView:cancel_subscription', username='******'))
        data = response.get_json()['data']

        assert response.status_code == 200
        assert data['deleted'] is True
        assert data['message'] == 'User\'s subscription has been cancelled.'

        user = User.find_by_identity('firstSub1')
        assert user.subscription is None
        assert user.cancelled_subscription_on <= \
            datetime.datetime.now(pytz.utc)
def seed():
    """
    Seed the database with an initial user. The username, email and password
    are taken from the app config.

    :return: User instance
    """

    params = {
        'role': 'admin',
        'email': app.config['SEED_ADMIN_EMAIL'],
        'username': app.config['SEED_ADMIN_USERNAME'],
        'password': app.config['SEED_ADMIN_PASSWORD'],
        'active': True
    }

    return User(**params).save()
Exemple #17
0
    def activate_account(self, activation_token):
        user = User.deserialize_token(activation_token)

        if user is None:
            err = 'Your activation token has expired or was tampered with.'
            return {'error': err}, 400

        user.active = True
        user.save()

        response = {
            'data': {
                'activated': True,
                'message': 'Your account has been activated.'
            }
        }
        headers = {'Location': url_for('AuthView:post')}
        return response, 200, headers
Exemple #18
0
    def post(self):
        json_data = request.get_json()

        if not json_data:
            response = jsonify({'error': 'Invalid input.'})
            return response, 400

        try:
            data = auth_schema.load(json_data)
        except ValidationError as err:
            response = jsonify({'error': err.messages})

            return response, 422

        user = User.find_by_identity(data['identity'])

        if user and user.authenticated(password=data['password']):
            if user.is_active():
                # identity is used to lookup a user on protected endpoints
                access_token = create_access_token(identity=user.username)

                user.update_activity_tracking(request.remote_addr)

                response = jsonify({'data': {'access_token': access_token}})

                # Set the JWTs and the CSRF double submit protection cookies
                # Clients such as web browsers support cookies and
                # "set_access_cookies" will set two cookies in the browser,
                # 1)access_token 2)CSRF token
                set_access_cookies(response, access_token)

                return response, 200
            else:
                error = ('This account is not active. If you recently signed'
                         ' up for an account, check your email for a'
                         ' verification link.')
                return jsonify({'error': error}), 400

        response = jsonify({'error': 'Invalid credentials.'})
        return response, 401
Exemple #19
0
    def cancel_subscription(self, username):
        """Admins can canel a user's subscription"""

        user = User.find_by_identity(username)

        if user is None:
            response = {'error': USER_NOT_FOUND}
            return response, 404

        if not user.subscription:
            error = '{0} doesn\'t have an active subscription.'.format(
                username)
            response = {'error': error}
            return response, 400

        subscription = Subscription()
        subscription.cancel(user=user)
        response = {
            'data': {
                'deleted': True,
                'message': 'User\'s subscription has been cancelled.'
            }
        }
        return response, 200
Exemple #20
0
 def test_deserialize_token(self, token):
     """User.deserialize_token de-serializes a JWS correctly"""
     user = User.deserialize_token(token)
     assert user.email == '*****@*****.**'
Exemple #21
0
 def test_is_active(self):
     user = User.find_by_identity('*****@*****.**')
     assert user.is_active() is True