diff --git a/.env_example b/.env_example index 3dba552..671c7f3 100644 --- a/.env_example +++ b/.env_example @@ -10,8 +10,7 @@ SENTRY_DSN= PAPERSWITHCODE_USER= PAPERSWITHCODE_PASS= DB_URI= -DB_URI= TWITTER_FREQ_HOURS= PAPERS_WITH_CODE_FREQ_HOURS= ARXIV_FREQ_HOURS= -FRONTEND_URL= \ No newline at end of file +FRONTEND_URL= diff --git a/README.md b/README.md index ed99ec7..1222738 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,80 @@ Read, collaborate and talk about scientific papers. ## Getting started -1. Install Postgres -2. Install `pandoc` to support references extraction from here: https://pandoc.org/installing.html -3. Install `pdftotext` to support acronyms extraction: `sudo apt-get install poppler-utils` -4. Create your Python 3.7 virtual env -5. Create `.env` file based on the `.env_example` and fill out the values -6. Run `flask fetch-papers` to grab some papers (you can stop the function after fetching ~200 papers) -7. Run `flask run` -8. See `SciHive.postman_collection.json` for some examples of queries +### 1) Install Postgres + +``` +podman run --name postgresql -p 5432:5432 -d postgres:latest +``` + +### Install pgadmin (optional) + +Change the default settings. + +``` +podman run --name pgadmin -p 5050:80 -e "PGADMIN_DEFAULT_EMAIL=pgadmin4@pgadmin.org" -e "PGADMIN_DEFAULT_PASSWORD=admin" -d dpage/pgadmin4 +``` + +### 2) Install Pandoc + +Pandoc is needed to support references extraction. Installation can be found here: https://pandoc.org/installing.html. + +#### Archlinux +``` +sudo pacman -S pandoc +``` + +### 3) Install pdftotext + +`pdftotext` is needed to support acronyms extraction. + +#### Archlinux +``` +sudo pacman -S poppler +``` + +#### Ubuntu +``` +sudo apt-get install poppler-utils +``` + +### 4) Configure a virtualenv + +``` +mkvirtualenv scihive +workon scihive + +pip install -r requirements.txt +``` + +### 5) Set the configuration variables in the .env + +Create `.env` file based on the `.env_example` and fill out the values + + +### 6) Prepare the backend + +Run `flask fetch-arxiv` to grab some papers (you can stop the function after fetching ~200 papers) + +### 7) Run the backend + +To start the backend +``` +flask run +``` + +To visualize the routes +``` +flask routes +``` + +### 8) See `SciHive.postman_collection.json` for some examples of queries ## Production - Repeat steps 2-5 - Run `sh restart_server.sh` -###Changelog +### Changelog -- May 31, 2019 - Acronym extraction and enrichment (from other papers) \ No newline at end of file +- May 31, 2019 - Acronym extraction and enrichment (from other papers) diff --git a/requirements.txt b/requirements.txt index 9fe0ee6..177aa77 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,6 +16,8 @@ flask-caching schedule +bson + boto3 Flask-RESTful Flask-JWT-Extended @@ -44,4 +46,4 @@ pep8 pylint-flask pylint-flask-sqlalchemy sqlalchemy-easy-profile -itsdangerous==1.1.0 \ No newline at end of file +itsdangerous==1.1.0 diff --git a/src/main.py b/src/main.py index 15afd1c..1c91b6e 100644 --- a/src/main.py +++ b/src/main.py @@ -14,6 +14,7 @@ from flask_caching import Cache from .routes.paper import app as paper_routes from .routes.comments import app as comments_routes +from .routes.replies import app as replies_routes from .routes.paper_list import app as paper_list_routes from .routes.user import app as user_routes from .routes.groups import app as groups_routes @@ -77,6 +78,7 @@ def before_send(event, hint): app.register_blueprint(paper_list_routes, url_prefix='/papers') app.register_blueprint(paper_routes, url_prefix='/paper') +app.register_blueprint(replies_routes, url_prefix='/reply') app.register_blueprint(comments_routes, url_prefix='/paper') app.register_blueprint(user_routes, url_prefix='/user') app.register_blueprint(groups_routes, url_prefix='/groups') @@ -108,7 +110,6 @@ def background_tasks(): def hello_world(): return 'Hello, World!' - @app.cli.command("migrate-db") @click.option('--path', help='folder path') def migrate_db(path): diff --git a/src/routes/replies.py b/src/routes/replies.py new file mode 100644 index 0000000..fd7f6da --- /dev/null +++ b/src/routes/replies.py @@ -0,0 +1,55 @@ +import logging +from datetime import datetime + +from flask import Blueprint +from flask_jwt_extended import get_jwt_identity, jwt_required +from flask_restful import (Api, Resource, abort, fields, inputs, marshal_with, reqparse) +from sqlalchemy import or_ +from typing import Optional +from src.new_backend.models import Collection, Comment, Paper, Reply, db, User +from .user_utils import get_user + +app = Blueprint('replies', __name__) +api = Api(app) +logger = logging.getLogger(__name__) + +replies_fields = { + 'id': fields.String, + 'user': fields.String(attribute='user.username'), + 'text': fields.String, + 'createdAt': fields.DateTime(dt_format='rfc822', attribute='creation_date'), +} + +EMPTY_FIELD_MSG = 'This field cannot be blank' + +class ReplyResource(Resource): + method_decorators = [jwt_required] + + def _get_reply(self, reply_id): + + reply = Reply.query.get_or_404(reply_id) + + user = get_user() + + if reply.user != user: + abort(403, message='unauthorized to modify the reply') + + return reply + + + @marshal_with(replies_fields, envelope='reply') + def post(self, reply_id): + + reply = self._get_reply(reply_id) + + edit_reply_parser = reqparse.RequestParser() + edit_reply_parser.add_argument('text', help=EMPTY_FIELD_MSG, type=str, location='json', required=False) + data = edit_reply_parser.parse_args() + reply.text = data['text'] + + db.session.commit() + + return reply + + +api.add_resource(ReplyResource, "/")