示例#1
0
def app():
    db_fd, db_path = tempfile.mkstemp()
    app = create_app({'TESTING': True, 'DATABASE': db_path})
    with app.app_context():
        init_db()
        get_db().executescript(_data_sql)
    yield app
    os.close(db_fd)
    os.unlink(db_path)
示例#2
0
def test_get_close_db(app):
    with app.app_context():
        db = get_db()
        assert db is get_db()

    with pytest.raises(sqlite3.ProgrammingError) as e:
        db.execute('SELECT 1')

    assert 'closed' in str(e.value)
示例#3
0
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        db = get_db()
        error = None
        user = db.execute('SELECT * FROM user WHERE username = ?',
                          (username, )).fetchone()

        if user is None:
            error = 'Incorrect username.'
        elif not check_password_hash(user['password'], password):
            error = 'Incorrect password.'

        if error is None:
            """
            session is a dict that stores data across requests.
            When validation succeeds, the user's id is stored in a new session
            The data is stored in a cookie that is sent to the browser
            and the browser then sends it back with subsequent requests.
            
            Now that the user's id is stored in the session, it will be available
            on subsequent requests. At the beginning of each request, if a user is
            logged in, 
            their information should be loaded and made available to other views.
            """
            session.clear()
            session['user_id'] = user['id']
            return redirect(url_for('main_index'))

        flash(error)
    return render_template('auth/login.html')
示例#4
0
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        db = get_db()
        error = None

        if not username:
            error = 'Username is required.'
        elif not password:
            error = 'Password is required.'
        # The database library will take care of escaping the values so you are not vulnerable to a SQL injection attack.
        elif db.execute('SELECT id FROM user WHERE username = ?',
                        (username, )).fetchone() is not None:
            error = 'User {} is already registered.'.format(username)

        if error is None:
            db.execute('INSERT INTO user (username,password) VALUES (?, ?)',
                       (username, generate_password_hash(password)))
            # Since this query modifies data, db.commit() needs to be called afterwards to save the changes.
            db.commit()
            # after storing the user, they are redirected to the login page.
            # url_for() generates the URL for the login view based on its name.
            # redirect() generates a redirect response to the generated URL
            return redirect(url_for('auth.login'))

        # flash 类似刷新
        flash(error)
    return render_template('auth/register.html')
示例#5
0
def load_logged_in_user():
    user_id = session.get('user_id')

    if user_id is None:
        g.user = None
    else:
        g.user = get_db().execute('SELECT * FROM user WHERE id = ?',
                                  (user_id, )).fetchone()
示例#6
0
def test_delete(client, auth, app):
    auth.login()
    response = client.post('blog/1/delete')
    assert response.headers['Location'] == 'http://localhost/blog/'

    with app.app_context():
        db = get_db()
        post = db.execute('SELECT * FROM post WHERE id = 1').fetchone()
        assert post is None
示例#7
0
def test_update(client, auth, app):
    auth.login()
    assert client.get('blog/1/update').status_code == 200
    client.post('blog/1/update', data={'title': 'updated', 'body': ''})

    with app.app_context():
        db = get_db()
        post = db.execute('SELECT * FROM post WHERE id = 1').fetchone()
        assert post['title'] == 'updated'
示例#8
0
def test_create(client, auth, app):
    auth.login()
    assert client.get('blog/create').status_code == 200
    client.post('blog/create', data={'title': 'created', 'body': ''})

    with app.app_context():
        db = get_db()
        count = db.execute('SELECT COUNT(id) FROM post').fetchone()[0]
        assert count == 2
示例#9
0
def test_register(client, app):
    assert client.get('/auth/register').status_code == 200
    response = client.post('/auth/register',
                           data={
                               'username': '******',
                               'password': '******'
                           })
    assert 'http://localhost/auth/login' == response.headers['Location']

    with app.app_context():
        assert get_db().execute(
            "select * from user where username = '******'", ).fetchone() is not None
示例#10
0
def test_author_required(app, client, auth):
    # change the post author to another user
    with app.app_context():
        db = get_db()
        db.execute('UPDATE post SET author_id = 2 WHERE id = 1')
        db.commit()

    auth.login()
    # current user can't modify other user's post
    assert client.post('blog/1/update').status_code == 403
    assert client.post('blog/1/delete').status_code == 403

    # current user doesn't see edit link
    assert b'href="blog/1/update"' not in client.get('/').data
示例#11
0
def update(id):
    post = get_post(id)
    if request.method == 'POST':
        title = request.form['title']
        body = request.form['body']
        error = None

        if not title:
            error = "Title is required."
        if error is not None:
            flash(error)
        else:
            db = get_db()
            db.execute('UPDATE post SET title = ?, body=?'
                       ' WHERE id=?', (title, body, id))
            db.commit()
            return redirect(url_for('blog.index'))

    return render_template('blog/update.html', post=post)
示例#12
0
def create():
    if request.method == 'POST':
        title = request.form['title']
        body = request.form['body']
        error = None

        if not title:
            error = 'Title is required.'

        if error is not None:
            flash(error)
        else:
            db = get_db()
            db.execute(
                'INSERT INTO post (title, body, author_id)'
                ' VALUES (?,?,?)', (title, body, g.user['id']))
            db.commit()
            return redirect(url_for('blog.index'))
    return render_template('blog/create.html')
示例#13
0
def get_post(id, check_author=True):
    post = get_db().execute(
        'SELECT p.id, title, body, created, author_id, username'
        ' FROM post p JOIN user u ON p.author_id = u.id'
        ' WHERE p.id=?', (id, )).fetchone()
    """
    404 means “Not Found”, and 403 means “Forbidden”. (401 means “Unauthorized”, but you redirect to the login page instead of returning that status.)

    check_author argument is defined so that the function can be used to get a post
    without checking the author.
    This would be useful if you wrote a view to show an individual post on a page, where the user doesn't
    matter because they're not modifying the post
    """
    if post is None:
        abort(404, "Post id {0} doesn't exist.".format(id))

    if check_author and post['author_id'] != g.user['id']:
        abort(403)

    return post
示例#14
0
def delete(id):
    get_post(id)
    db = get_db()
    db.execute('DELETE FROM post WHERE id=?', (id, ))
    db.commit()
    return redirect(url_for('blog.index'))
示例#15
0
def index():
    db = get_db()
    posts = db.execute('SELECT p.id, title, body, created, author_id, username'
                       ' FROM post p JOIN user u ON p.author_id = u.id'
                       ' ORDER BY created DESC').fetchall()
    return render_template('blog/index.html', posts=posts)