diff --git a/code/backend/nest_backend/__main__.py b/code/backend/nest_backend/__main__.py index 374686a..e4ea470 100644 --- a/code/backend/nest_backend/__main__.py +++ b/code/backend/nest_backend/__main__.py @@ -8,6 +8,7 @@ from .gestione import * from .app import app, extension_sqlalchemy from .database import User +print(" * N.E.S.T. Server is now starting. Please hold up.") print(" * Swagger docs will be available at http://127.0.0.1:5000/docs") @@ -20,5 +21,5 @@ with app.app_context(): User(email="admin@admin.com", password=gen_password("password"), username="admin", isAdmin=True)) extension_sqlalchemy.session.commit() print(" * Created! Username: admin | Password: password") - +print(" * N.E.S.T. is based on Gestione and coded by the N.E.S.T. team.") app.run(debug=__debug__) diff --git a/code/backend/nest_backend/api_schemas.py b/code/backend/nest_backend/api_schemas.py index 9a7848f..754f390 100644 --- a/code/backend/nest_backend/api_schemas.py +++ b/code/backend/nest_backend/api_schemas.py @@ -63,6 +63,16 @@ class RepositorySchema(Schema): evaluation_mode = fields.Integer(description="The mode with which conditions are evaluated.") +class TweetSchema(Schema): + snowflake = fields.String(description="The tweet identifier.") + content = fields.String(description="The content of the tweet.") + location = fields.String(description="The location (coordinates) from which the tweet was tweeted.") + place = fields.String(description="The place from which the tweet was tweeted.") + poster = fields.String(default="The one that created the tweet.") + insert_time = fields.DateTime(default="The time on which the tweet was captured.") + conditions = fields.Nested(ConditionSchema, many=True) + + class CreateRepository(Schema): name = fields.String(description="The repository name.") diff --git a/code/backend/nest_backend/api_spec.py b/code/backend/nest_backend/api_spec.py index aed57af..0f8264f 100644 --- a/code/backend/nest_backend/api_spec.py +++ b/code/backend/nest_backend/api_spec.py @@ -31,6 +31,7 @@ spec.components.schema("CreateCondition", schema=CreateCondition) spec.components.schema("ConditionParameter", schema=ConditionParameterSchema) spec.components.schema("AlertParameter", schema=AlertParameterSchema) spec.components.schema("Alert", schema=Alert) +spec.components.schema("Tweet", schema=TweetSchema) spec.components.schema("CreateAlert", schema=CreateAlert) spec.components.security_scheme("jwt", {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}) diff --git a/code/backend/nest_backend/app.py b/code/backend/nest_backend/app.py index e038b0c..15ca7eb 100644 --- a/code/backend/nest_backend/app.py +++ b/code/backend/nest_backend/app.py @@ -66,6 +66,11 @@ app.add_url_rule( view_func=routes.page_repository_alerts, methods=["GET", "POST"] ) +app.add_url_rule( + "/api/v1/repositories//tweets", + view_func=routes.page_repository_tweets, + methods=["GET"] +) app.add_url_rule( "/api/v1/alert/", view_func=routes.page_alert, diff --git a/code/backend/nest_backend/database/tables/Tweet.py b/code/backend/nest_backend/database/tables/Tweet.py index f858179..c7f5d6f 100644 --- a/code/backend/nest_backend/database/tables/Tweet.py +++ b/code/backend/nest_backend/database/tables/Tweet.py @@ -9,8 +9,15 @@ class Tweet(ext.Model): __tablename__ = "tweet" snowflake = ext.Column(ext.String, primary_key=True) content = ext.Column(ext.String) - location = ext.Column(ext.String) # Todo: see if a dedicated class for locations is needed. This is likely. - poster = ext.Column(ext.String) # Todo: see if a dedicated class for posters is needed. + location = ext.Column(ext.String) + place = ext.Column(ext.String) + poster = ext.Column(ext.String) + insert_time = ext.Column(ext.DateTime, nullable=False) # Relationships repositories = ext.relationship("Composed", back_populates="tweet", cascade="all, delete") conditions = ext.relationship("Contains", back_populates="tweet", cascade="all, delete") + + def to_json(self): + return {"snowflake": self.snowflake, "content": self.content, "location": self.location, "poster": self.poster, + "place": self.place, "insert_time": self.insert_time.isoformat(), + "conditions": [c.condition.to_json() for c in self.conditions]} diff --git a/code/backend/nest_backend/routes/repository/__init__.py b/code/backend/nest_backend/routes/repository/__init__.py index a358981..44dc306 100644 --- a/code/backend/nest_backend/routes/repository/__init__.py +++ b/code/backend/nest_backend/routes/repository/__init__.py @@ -3,6 +3,7 @@ from .repository import page_repository from .repositories import page_repositories from .conditions import * from .alerts import * +from .tweets import * __all__ = ["page_condition", "page_repository_conditions", "page_repositories", - "page_alert", "page_repository", "page_repository_alerts"] + "page_alert", "page_repository", "page_repository_alerts", "page_repository_tweets"] diff --git a/code/backend/nest_backend/routes/repository/tweets/__init__.py b/code/backend/nest_backend/routes/repository/tweets/__init__.py new file mode 100644 index 0000000..2a2ff60 --- /dev/null +++ b/code/backend/nest_backend/routes/repository/tweets/__init__.py @@ -0,0 +1,2 @@ +from .repository_tweets import page_repository_tweets +__all__ = ["page_repository_tweets"] \ No newline at end of file diff --git a/code/backend/nest_backend/routes/repository/tweets/repository_tweets.py b/code/backend/nest_backend/routes/repository/tweets/repository_tweets.py new file mode 100644 index 0000000..aa60f86 --- /dev/null +++ b/code/backend/nest_backend/routes/repository/tweets/repository_tweets.py @@ -0,0 +1,54 @@ +from flask import request +from flask_jwt_extended import jwt_required +from nest_backend.gestione import repository_auth, json_error, json_success, ConditionType, Condition, Repository, \ + find_user, get_jwt_identity +from nest_backend.database import ext +from flask_cors import cross_origin +from nest_backend.gestione import hashtag_validator + + +@cross_origin() +@jwt_required() +@repository_auth +def page_repository_tweets(rid): + """ + --- + get: + summary: Get a list of a repository tweets. + parameters: + - in: path + schema: IntegerParameterSchema + security: + - jwt: [] + responses: + '200': + description: List of Tweet schemas, incapsulated in Success. + '401': + description: The user is not logged in. + content: + application/json: + schema: Error + '403': + description: The user is not authorized. + content: + application/json: + schema: Error + '404': + description: The repository could not be found. + content: + application/json: + schema: Error + tags: + - repository-related + """ + + repository = Repository.query.filter_by(id=rid).first() + if not repository: + return json_error("Could not find repository"), 404 + user = find_user(get_jwt_identity()) + + if user.email != repository.owner_id: + return json_error("You are not authorized."), 403 + + if request.method == "GET": + return json_success([t.tweet.to_json() for t in repository.tweets])