Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed MarkupSafe version to 1.1 to avoid error #465

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Dockerfile 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM python:3.6-alpine

ENV FLASK_APP flasky.py
ENV FLASK_CONFIG production

RUN adduser -D flasky
USER flasky

WORKDIR /home/flasky

COPY requirements requirements
RUN python -m venv venv
RUN venv/bin/pip install -r requirements/docker.txt

COPY app app
COPY migrations migrations
COPY flasky.py config.py boot.sh ./

# run-time configuration
EXPOSE 5000
ENTRYPOINT ["./boot.sh"]
1 change: 1 addition & 0 deletions Procfile 2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn flasky:app
5 changes: 5 additions & 0 deletions app/api/__init__ 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from flask import Blueprint

api = Blueprint('api', __name__)

from . import authentication, posts, users, comments, errors
44 changes: 44 additions & 0 deletions app/api/authentication 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from flask import g, jsonify
from flask_httpauth import HTTPBasicAuth
from ..models import User
from . import api
from .errors import unauthorized, forbidden

auth = HTTPBasicAuth()


@auth.verify_password
def verify_password(email_or_token, password):
if email_or_token == '':
return False
if password == '':
g.current_user = User.verify_auth_token(email_or_token)
g.token_used = True
return g.current_user is not None
user = User.query.filter_by(email=email_or_token.lower()).first()
if not user:
return False
g.current_user = user
g.token_used = False
return user.verify_password(password)


@auth.error_handler
def auth_error():
return unauthorized('Invalid credentials')


@api.before_request
@auth.login_required
def before_request():
if not g.current_user.is_anonymous and \
not g.current_user.confirmed:
return forbidden('Unconfirmed account')


@api.route('/tokens/', methods=['POST'])
def get_token():
if g.current_user.is_anonymous or g.token_used:
return unauthorized('Invalid credentials')
return jsonify({'token': g.current_user.generate_auth_token(
expiration=3600), 'expiration': 3600})
67 changes: 67 additions & 0 deletions app/api/comments 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from flask import jsonify, request, g, url_for, current_app
from .. import db
from ..models import Post, Permission, Comment
from . import api
from .decorators import permission_required


@api.route('/comments/')
def get_comments():
page = request.args.get('page', 1, type=int)
pagination = Comment.query.order_by(Comment.timestamp.desc()).paginate(
page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
error_out=False)
comments = pagination.items
prev = None
if pagination.has_prev:
prev = url_for('api.get_comments', page=page-1)
next = None
if pagination.has_next:
next = url_for('api.get_comments', page=page+1)
return jsonify({
'comments': [comment.to_json() for comment in comments],
'prev': prev,
'next': next,
'count': pagination.total
})


@api.route('/comments/<int:id>')
def get_comment(id):
comment = Comment.query.get_or_404(id)
return jsonify(comment.to_json())


@api.route('/posts/<int:id>/comments/')
def get_post_comments(id):
post = Post.query.get_or_404(id)
page = request.args.get('page', 1, type=int)
pagination = post.comments.order_by(Comment.timestamp.asc()).paginate(
page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
error_out=False)
comments = pagination.items
prev = None
if pagination.has_prev:
prev = url_for('api.get_post_comments', id=id, page=page-1)
next = None
if pagination.has_next:
next = url_for('api.get_post_comments', id=id, page=page+1)
return jsonify({
'comments': [comment.to_json() for comment in comments],
'prev': prev,
'next': next,
'count': pagination.total
})


@api.route('/posts/<int:id>/comments/', methods=['POST'])
@permission_required(Permission.COMMENT)
def new_post_comment(id):
post = Post.query.get_or_404(id)
comment = Comment.from_json(request.json)
comment.author = g.current_user
comment.post = post
db.session.add(comment)
db.session.commit()
return jsonify(comment.to_json()), 201, \
{'Location': url_for('api.get_comment', id=comment.id)}
14 changes: 14 additions & 0 deletions app/api/decorators 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from functools import wraps
from flask import g
from .errors import forbidden


def permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not g.current_user.can(permission):
return forbidden('Insufficient permissions')
return f(*args, **kwargs)
return decorated_function
return decorator
26 changes: 26 additions & 0 deletions app/api/errors 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from flask import jsonify
from app.exceptions import ValidationError
from . import api


def bad_request(message):
response = jsonify({'error': 'bad request', 'message': message})
response.status_code = 400
return response


def unauthorized(message):
response = jsonify({'error': 'unauthorized', 'message': message})
response.status_code = 401
return response


def forbidden(message):
response = jsonify({'error': 'forbidden', 'message': message})
response.status_code = 403
return response


@api.errorhandler(ValidationError)
def validation_error(e):
return bad_request(e.args[0])
57 changes: 57 additions & 0 deletions app/api/posts 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from flask import jsonify, request, g, url_for, current_app
from .. import db
from ..models import Post, Permission
from . import api
from .decorators import permission_required
from .errors import forbidden


@api.route('/posts/')
def get_posts():
page = request.args.get('page', 1, type=int)
pagination = Post.query.paginate(
page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
error_out=False)
posts = pagination.items
prev = None
if pagination.has_prev:
prev = url_for('api.get_posts', page=page-1)
next = None
if pagination.has_next:
next = url_for('api.get_posts', page=page+1)
return jsonify({
'posts': [post.to_json() for post in posts],
'prev': prev,
'next': next,
'count': pagination.total
})


@api.route('/posts/<int:id>')
def get_post(id):
post = Post.query.get_or_404(id)
return jsonify(post.to_json())


@api.route('/posts/', methods=['POST'])
@permission_required(Permission.WRITE)
def new_post():
post = Post.from_json(request.json)
post.author = g.current_user
db.session.add(post)
db.session.commit()
return jsonify(post.to_json()), 201, \
{'Location': url_for('api.get_post', id=post.id)}


@api.route('/posts/<int:id>', methods=['PUT'])
@permission_required(Permission.WRITE)
def edit_post(id):
post = Post.query.get_or_404(id)
if g.current_user != post.author and \
not g.current_user.can(Permission.ADMIN):
return forbidden('Insufficient permissions')
post.body = request.json.get('body', post.body)
db.session.add(post)
db.session.commit()
return jsonify(post.to_json())
53 changes: 53 additions & 0 deletions app/api/users 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from flask import jsonify, request, current_app, url_for
from . import api
from ..models import User, Post


@api.route('/users/<int:id>')
def get_user(id):
user = User.query.get_or_404(id)
return jsonify(user.to_json())


@api.route('/users/<int:id>/posts/')
def get_user_posts(id):
user = User.query.get_or_404(id)
page = request.args.get('page', 1, type=int)
pagination = user.posts.order_by(Post.timestamp.desc()).paginate(
page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
error_out=False)
posts = pagination.items
prev = None
if pagination.has_prev:
prev = url_for('api.get_user_posts', id=id, page=page-1)
next = None
if pagination.has_next:
next = url_for('api.get_user_posts', id=id, page=page+1)
return jsonify({
'posts': [post.to_json() for post in posts],
'prev': prev,
'next': next,
'count': pagination.total
})


@api.route('/users/<int:id>/timeline/')
def get_user_followed_posts(id):
user = User.query.get_or_404(id)
page = request.args.get('page', 1, type=int)
pagination = user.followed_posts.order_by(Post.timestamp.desc()).paginate(
page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
error_out=False)
posts = pagination.items
prev = None
if pagination.has_prev:
prev = url_for('api.get_user_followed_posts', id=id, page=page-1)
next = None
if pagination.has_next:
next = url_for('api.get_user_followed_posts', id=id, page=page+1)
return jsonify({
'posts': [post.to_json() for post in posts],
'prev': prev,
'next': next,
'count': pagination.total
})
19 changes: 19 additions & 0 deletions app/decorators 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from functools import wraps
from flask import abort
from flask_login import current_user
from .models import Permission


def permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.can(permission):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator


def admin_required(f):
return permission_required(Permission.ADMIN)(f)
2 changes: 2 additions & 0 deletions app/exceptions 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ValidationError(ValueError):
pass
37 changes: 37 additions & 0 deletions app/fake 2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from random import randint
from sqlalchemy.exc import IntegrityError
from faker import Faker
from . import db
from .models import User, Post


def users(count=100):
fake = Faker()
i = 0
while i < count:
u = User(email=fake.email(),
username=fake.user_name(),
password='password',
confirmed=True,
name=fake.name(),
location=fake.city(),
about_me=fake.text(),
member_since=fake.past_date())
db.session.add(u)
try:
db.session.commit()
i += 1
except IntegrityError:
db.session.rollback()


def posts(count=100):
fake = Faker()
user_count = User.query.count()
for i in range(count):
u = User.query.offset(randint(0, user_count - 1)).first()
p = Post(body=fake.text(),
timestamp=fake.past_date(),
author=u)
db.session.add(p)
db.session.commit()
Loading