def index(): data = { 'documentation_url': 'http://graygram.readthedocs.io/en/latest/', 'ios_repo_url': 'https://github.com/devxoul/graygram-ios', 'web_repo_url': 'https://github.com/devxoul/graygram-web', } return render_json(data)
def upload_photo(): if 'file' not in request.files: raise BadRequest("Missing parameter: 'file'") try: photo = m.Photo.upload(file=request.files['file']) except photo_uploader.InvalidImage: raise BadRequest("Invalid image") return render_json(photo), 201
def username(): """Create a new user with username and password. **Example request**: .. sourcecode:: http POST /join/username HTTP/1.1 Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 201 OK Content-Type: application/json { "username": "******", "photo": null, "created_at": "2017-02-21T16:59:35+0000", "id": 1 } :form username: Username of the user :form password: Password of the user :statuscode 201: Succeeded to create a new user :statuscode 400: Missing or wrong parameters :statuscode 409: User already exists """ username = request.values.get('username') if not username: raise BadRequest(message="Missing parameter", field='username') password = request.values.get('password') if not password: raise BadRequest(message="Missing parameter", field='password') cred = m.Credential.query.filter_by(type='username', key=username).first() if cred: raise Conflict(message="User '{}' already exists.".format(username), field='username') user = m.User.create(username=username, password=password) try: db.session.commit() except IntegrityError: db.session.rollback() raise Conflict(message="User '{}' already exists.".format(username), field='username') login_user(user, remember=True) return render_json(user), 201
def update_me_photo(): if 'photo' not in request.files: raise BadRequest(message="Missing parameter", field='photo') try: photo = m.Photo.upload(file=request.files['photo']) except InvalidImage: raise BadRequest(message="Invalid image", field='photo') current_user.photo = photo db.session.add(current_user) db.session.commit() return render_json(current_user.serialize())
def create_post(): """Create a post **Example JSON response**: .. sourcecode:: json { "message": "생 마르탱 운하에서 본 할머니와 할아버지", "id": 14, "is_liked": false, "like_count": 0, "user": { "created_at": "2017-02-07T09:23:13+0000", "photo": { "id": "d7394923-cf39-4c78-891a-8714eb615ea7" }, "username": "******", "id": 1 }, "created_at": "2017-01-27T19:52:32+0000", "photo": { "id": "69e892b4-7dbd-403c-92fc-07f199c2be35" } } :form photo: An image file :form message: A message (Optional) :statuscode 201: Created :statuscode 400: Required parameter is missing or invalid :statuscode 401: Not authorized """ if 'photo' not in request.files: raise BadRequest(message="Missing parameter", field='photo') try: photo = m.Photo.upload(file=request.files['photo']) except InvalidImage: raise BadRequest(message="Invalid image", field='photo') message = request.values.get('message') post = m.Post() post.user = current_user post.photo = photo post.message = message db.session.add(post) db.session.commit() return render_json(post), 201
def username(): """Login using username and password. **Example request**: .. sourcecode:: http POST /login/username HTTP/1.1 Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "username": "******", "photo": null, "created_at": "2017-02-21T16:59:35+0000", "id": 1 } :form username: Username of the user :form password: Password of the user :statuscode 200: Succeeded to login :statuscode 400: Missing or wrong parameters """ username = request.values.get('username') if not username: raise BadRequest(message="Missing parameter", field='username') password = request.values.get('password') if not password: raise BadRequest(message="Missing parameter", field='password') cred = m.Credential.query.filter_by(type='username', key=username).first() if not cred: raise BadRequest(message="User not registered", field='username') password_correct = bcrypt.check_password_hash(cred.value, password) if not password_correct: raise BadRequest(message="Wrong password", field='password') login_user(cred.user, remember=True) return render_json(cred.user)
def get_me(): """Get my profile **Example JSON response**: .. sourcecode:: json { "username": "******", "photo": null, "created_at": "2017-02-21T16:59:35+0000", "id": 1 } :statuscode 401: Not authorized """ return render_json(current_user.serialize())
def delete_post(post_id): """ Delete the post **Example JSON response**: .. sourcecode:: json {} :statuscode 200: Deleted :statuscode 401: Not authorized :statuscode 403: No permission """ post = m.Post.query.get_or_404(post_id) if post.user != current_user: raise Forbidden() db.session.delete(post) db.session.commit() return render_json({})
def get_likes(post_id): """Get users who like the post **Example JSON response**: .. sorucecode:: json { "data": [ { "username": "******", "photo": null, "created_at": "2017-02-21T16:59:35+0000", "id": 1 } ], "paging": { "next": null } } :statuscode 200: OK :statuscode 404: There's no post """ post = m.Post.query.get_or_404(post_id) limit = request.values.get('limit', 30, type=int) offset = request.values.get('offset', 0, type=int) post_likes = m.PostLike.query \ .filter_by(post=post) \ .order_by(m.PostLike.liked_at.desc()) \ .offset(offset) \ .limit(limit) data = { 'data': [post_like.serialize() for post_like in post_likes], 'paging': None, } if limit + offset < m.Post.query.count(): data['paging'] = { 'next': next_url(limit=limit, offset=offset), } return render_json(data)
def unlike_post(post_id): """Unlike the post **Example JSON response**: .. sourcecode:: json {} :statuscode 200: Unliked :statuscode 401: Not authorized :statuscode 409: Already unliked """ post = m.Post.query.get_or_404(post_id) cache.delete_memoized('is_liked_by', post, current_user) if not post.is_liked: raise Conflict() post.is_liked = False db.session.add(post) db.session.commit() return render_json({})
def logout(): """Logout from the current session. **Example request**: .. sourcecode:: http GET /logout HTTP/1.1 Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json {} """ logout_user() return render_json({})
def get_post(post_id): """Get a single post. **Example JSON response**: .. sourcecode:: json { "message": "생 마르탱 운하에서 본 할머니와 할아버지", "id": 14, "is_liked": false, "like_count": 0, "user": { "created_at": "2017-02-07T09:23:13+0000", "photo": { "id": "d7394923-cf39-4c78-891a-8714eb615ea7" }, "username": "******", "id": 1 }, "created_at": "2017-01-27T19:52:32+0000", "photo": { "id": "69e892b4-7dbd-403c-92fc-07f199c2be35" } } :>json int id: :>json Photo photo: :>json string message: A message (Optional) :>json User user: Post author :>json date created_at: :statuscode 200: OK :statuscode 404: There's no post """ post = m.Post.query.get_or_404(post_id) return render_json(post)
def update_post(post_id): """Edit the post **Example JSON response**: .. sourcecode:: json { "message": "생 마르탱 운하에서 본 할머니와 할아버지", "id": 14, "is_liked": false, "like_count": 0, "user": { "created_at": "2017-02-07T09:23:13+0000", "photo": { "id": "d7394923-cf39-4c78-891a-8714eb615ea7" }, "username": "******", "id": 1 }, "created_at": "2017-01-27T19:52:32+0000", "photo": { "id": "69e892b4-7dbd-403c-92fc-07f199c2be35" } } :form message: New message (Optional) :statuscode 200: OK :statuscode 401: Not authorized :statuscode 403: No permission """ post = m.Post.query.get_or_404(post_id) if post.user != current_user: raise Forbidden() post.message = request.values.get('message') db.session.add(post) db.session.commit() return render_json(post)
def feed(): """ **Example request**: .. sourcecode:: http GET /feed HTTP/1.1 Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "data": [ { "message": "생 마르탱 운하에서 본 할머니와 할아버지", "id": 14, "is_liked": false, "like_count": 0, "user": { "created_at": "2017-02-07T09:23:13+0000", "photo": { "id": "d7394923-cf39-4c78-891a-8714eb615ea7" }, "username": "******", "id": 1 }, "created_at": "2017-01-27T19:52:32+0000", "photo": { "id": "69e892b4-7dbd-403c-92fc-07f199c2be35" } }, { "message": "서울의 한 골목", "id": 13, "is_liked": false, "like_count": 0, "user": { "created_at": "2017-02-07T09:23:13+0000", "photo": { "id": "d7394923-cf39-4c78-891a-8714eb615ea7" }, "username": "******", "id": 1 }, "created_at": "2017-01-27T19:52:02+0000", "photo": { "id": "1e6833e2-f041-49be-9e4a-5691d084910d" } } ], "paging": { "next": "https://www.graygram.com/feed?limit=2&offset=2" }, } :query limit: :query offset: :>json array data: Array of ``Post`` :>json string paging.next: (Optional) Next page URL """ limit = request.values.get('limit', 30, type=int) offset = request.values.get('offset', 0, type=int) posts = m.Post.query \ .order_by(m.Post.created_at.desc()) \ .offset(offset) \ .limit(limit) data = { 'data': [post.serialize() for post in posts], 'paging': None, } if limit + offset < m.Post.query.count(): data['paging'] = { 'next': next_url(limit=limit, offset=offset), } return render_json(data)
def delete_me_photo(): current_user.photo = None db.session.add(current_user) db.session.commit() return render_json(current_user.serialize())