diff --git a/app/controller/__init__.py b/app/controller/__init__.py index 969f6f3b..a5273a05 100644 --- a/app/controller/__init__.py +++ b/app/controller/__init__.py @@ -29,6 +29,9 @@ def init_app(app): from . import student_resources student_resources.configure(api) + from . import report_resources + report_resources.configure(api) + app.register_blueprint(api_bp) @app.route("/") diff --git a/app/controller/post_resources.py b/app/controller/post_resources.py index 35bf8b14..9d1aa4df 100644 --- a/app/controller/post_resources.py +++ b/app/controller/post_resources.py @@ -22,6 +22,16 @@ def post(self): except ValidationError as err: return make_response(jsonify(err.messages), 400) + @jwt_required() + def get(self): + user = current_user + if not user.is_professor(): + ps = post_schema.PostSchema( + many=True, context={'reg_student': user.reg}) + else: + ps = post_schema.PostSchema(many=True) + return make_response(ps.jsonify(user.posts), 200) + class PostAgreesList(Resource): @student_required() diff --git a/app/controller/report_resources.py b/app/controller/report_resources.py new file mode 100644 index 00000000..0addd5bf --- /dev/null +++ b/app/controller/report_resources.py @@ -0,0 +1,21 @@ +from flask_restful import Resource +from flask import request, make_response, jsonify +from ..schemas import report_schema +from ..services import report_services +from marshmallow import ValidationError +from flask_jwt_extended import jwt_required, current_user + +class ReportList(Resource): + @jwt_required() + def post(self): + try: + user = current_user + rs = report_schema.ReportSchema() + report = rs.load(request.json) + message, status_code = report_services.register_report(report, user) + return make_response(jsonify(message), status_code) + except ValidationError as err: + return make_response(jsonify(err.messages), 400) + +def configure(api): + api.add_resource(ReportList, "/report") \ No newline at end of file diff --git a/app/model/post.py b/app/model/post.py index f31294f1..eb8225c0 100644 --- a/app/model/post.py +++ b/app/model/post.py @@ -64,5 +64,9 @@ def delete_feedbacks(post_db): db.session.delete(disagree) db.session.commit() + @staticmethod def delete_reports(post_db): - pass + from .report import Report + for report in Report.query.filter_by(id_post=post_db.id_post).all(): + db.session.delete(report) + db.session.commit() diff --git a/app/model/professor.py b/app/model/professor.py index b4a245c3..7c52135e 100644 --- a/app/model/professor.py +++ b/app/model/professor.py @@ -22,6 +22,9 @@ class Professor(db.Model): def reg(self): return self.reg_professor + def is_professor(self): + return True + @property def password(self): raise AttributeError('password: write-only field') diff --git a/app/model/report.py b/app/model/report.py index 37e534a7..ec8370d1 100644 --- a/app/model/report.py +++ b/app/model/report.py @@ -1,19 +1,18 @@ from app.ext.database import db -import enum - - -class ReportTypes(enum.Enum): - linguagem_ofensiva = 'L' - incoerencia = 'I' - grave = 'G' - outros = 'O' class Report(db.Model): __tablename__ = "report" id_report = db.Column(db.Integer, primary_key=True) - id_post = db.Column(db.Integer, db.ForeignKey("post.id_post"), nullable=False) + id_post = db.Column(db.Integer, db.ForeignKey( + "post.id_post"), nullable=False) content = db.Column(db.String(120), nullable=False, default='') - reg_student = db.Column(db.Integer, db.ForeignKey("student.reg_student"), nullable=False) - report_type = db.Column(db.Enum(ReportTypes), nullable=False) + reg_student = db.Column(db.Integer, db.ForeignKey( + "student.reg_student")) + id_professor = db.Column(db.Integer, db.ForeignKey( + "professor.id_professor")) + offensive = db.Column(db.Boolean, nullable=False) + prejudice = db.Column(db.Boolean, nullable=False) + unrelated = db.Column(db.Boolean, nullable=False) + others = db.Column(db.Boolean, nullable=False) diff --git a/app/model/student.py b/app/model/student.py index b70ee48e..b4ad9153 100644 --- a/app/model/student.py +++ b/app/model/student.py @@ -23,6 +23,9 @@ class Student(db.Model): def reg(self): return self.reg_student + def is_professor(self): + return False + @property def password(self): raise AttributeError('password: write-only field') diff --git a/app/schemas/post_schema.py b/app/schemas/post_schema.py index 1e1cf2c0..9c878437 100644 --- a/app/schemas/post_schema.py +++ b/app/schemas/post_schema.py @@ -7,9 +7,9 @@ class Meta: model = post.Post id_post = fields.Integer(required=True, validate=validate.Range(min=0)) - reg_student = fields.Integer(required=True, validate=validate.Range(min=0)) + reg_student = fields.Integer(required=True, validate=validate.Range(min=0), load_only=True) id_professor = fields.Integer(required=True, validate=validate.Range(min=0)) - discipline_code = fields.String(required=True, validate=validate.Length(max=80)) + discipline_code = fields.String(required=True, validate=validate.Length(max=80), load_only=True) content = fields.String(required=True, validate=validate.Length(min=1, max=480)) rating = fields.Float(required=True, validate=validate.Range(min=0, max=10)) is_anonymous = fields.Boolean(required=True) diff --git a/app/schemas/report_schema.py b/app/schemas/report_schema.py new file mode 100644 index 00000000..4e8069d6 --- /dev/null +++ b/app/schemas/report_schema.py @@ -0,0 +1,14 @@ +from . import ma +from marshmallow import fields, validate +from ..model import report + +class ReportSchema(ma.SQLAlchemySchema): + class Meta: + model = report.Report + + id_post = fields.Integer(required=True, validate=validate.Range(min=0)) + content = fields.String(required=True, validate=validate.Length(min=10, max=120)) + offensive = fields.Boolean(required=True) + prejudice = fields.Boolean(required=True) + unrelated = fields.Boolean(required=True) + others = fields.Boolean(required=True) \ No newline at end of file diff --git a/app/services/post_services.py b/app/services/post_services.py index 168f9c4d..9f14ed50 100644 --- a/app/services/post_services.py +++ b/app/services/post_services.py @@ -74,4 +74,6 @@ def undisagree_post(post_db, student_db): def disagree_post(post_db, student_db): post_db.disagrees.append(student_db) db.session.commit() - return post_db, 200 + + return post_db, 200 + diff --git a/app/services/report_services.py b/app/services/report_services.py new file mode 100644 index 00000000..810df2a9 --- /dev/null +++ b/app/services/report_services.py @@ -0,0 +1,28 @@ +from ..model.report import Report +from ..ext.database import db +from . import student_services, post_services +from ..model.post import Post + + +def register_report(report, user): + message, status_code = validate_post(report.get('id_post')) + + if(status_code == 404): + return message, status_code + + report_db = Report(id_post=report.get( + 'id_post'), content=report.get('content'), offensive=report.get('offensive'), prejudice=report.get('prejudice'), unrelated=report.get('unrelated'), others=report.get('others')) + if(user.is_professor()): + report_db.id_professor = user.id_professor + else: + report_db.reg_student = user.reg_student + db.session.add(report_db) + db.session.commit() + + return {'message': "Report successfully added"}, 201 + +def validate_post(id_post): + if Post.get(id_post = id_post) is None: + return {'message': "Post not found!"}, 404 + return None, None + diff --git a/app/services/student_services.py b/app/services/student_services.py index 47f855b8..0b940c76 100644 --- a/app/services/student_services.py +++ b/app/services/student_services.py @@ -26,12 +26,6 @@ def __validate_student_relationship(student): return None, 200 - -def get_student_reg(reg_student): - student = Student.query.filter_by(reg_student=reg_student).first() - return student - - def delete_student(student_db): Student.delete(student_db) return {'message': "Student successfully deleted!"}, 204 diff --git a/database/database.sql b/database/database.sql index 4c78e4cd..0e55290d 100644 --- a/database/database.sql +++ b/database/database.sql @@ -82,9 +82,14 @@ CREATE TABLE IF NOT EXISTS report( id_report int UNSIGNED AUTO_INCREMENT, id_post int UNSIGNED NOT NULL, content varchar(120) NOT NULL DEFAULT '', - report_type enum('L', 'I', 'G', 'O') NOT NULL, - reg_student int UNSIGNED NOT NULL, + offensive TINYINT(1) NOT NULL, + prejudice TINYINT(1) NOT NULL, + unrelated TINYINT(1) NOT NULL, + others TINYINT(1) NOT NULL, + reg_student int UNSIGNED, + id_professor int UNSIGNED, PRIMARY KEY (id_report), FOREIGN KEY (id_post) REFERENCES post (id_post), - FOREIGN KEY (reg_student) REFERENCES student (reg_student) + FOREIGN KEY (reg_student) REFERENCES student (reg_student), + FOREIGN KEY (id_professor) REFERENCES professor (id_professor) )ENGINE InnoDB AUTO_INCREMENT = 0; \ No newline at end of file diff --git a/tests/flask_base_tests_cases.py b/tests/flask_base_tests_cases.py index 7b7133eb..727d041a 100644 --- a/tests/flask_base_tests_cases.py +++ b/tests/flask_base_tests_cases.py @@ -1,6 +1,6 @@ from unittest import TestCase from app.app import create_app -from app.model import course, discipline, professor +from app.model import course, discipline, professor, post from flask import url_for from json import loads @@ -111,8 +111,17 @@ def create_base_student(self): self.client.post(url_for("restapi.studentlist"), json=self.student) + # def create_base_post(self): + # if self.poste: + # return + # from tests_post import valid_post, valid_post_id + # self.poste = valid_post_id(self) + + # self.client.post(url_for('restapi.postlist'), json=self.poste) + def __create_atribute_entities(self): self.course = None self.discipline = None self.student = None self.professor = None + #self.poste = None diff --git a/tests/tests_post.py b/tests/tests_post.py index 34e4b8f9..21af32c1 100644 --- a/tests/tests_post.py +++ b/tests/tests_post.py @@ -18,6 +18,13 @@ def valid_post_id(self): "id_post": 1, } +def get_posts(self, headers=None): + if headers is None: + headers = self.create_student_token() + + return self.client.get(url_for('restapi.postlist'), headers = headers) + + def register_post(self, post=None, headers=None): if headers is None: headers = self.create_student_token() @@ -109,6 +116,25 @@ def test_api_must_validate_discipline_relationship_not_found(self): self.assertEqual(response.status_code, 404) self.assertEqual(response.json['message'], "Discipline not found!") +class TestGetPostList(TestFlaskBase): + + def test_must_get_student_post_found_empty(self): + response = get_posts(self) + status_code_expected = 200 + + self.assertEqual(response.status_code, status_code_expected) + self.assertEqual(response.json, []) + + def test_must_get_student_post_found(self): + register_post(self) + response = get_posts(self) + status_code_expected = 200 + self.assertEqual(response.status_code, status_code_expected) + + + + + class TestPostAgree(TestFlaskBase): def test_api_must_agree_post(self): diff --git a/tests/tests_report.py b/tests/tests_report.py new file mode 100644 index 00000000..c9b25249 --- /dev/null +++ b/tests/tests_report.py @@ -0,0 +1,80 @@ +from flask_base_tests_cases import TestFlaskBase +from flask import url_for, jsonify +from tests_post import register_post, valid_post_id + +def valid_report(self): + self.create_base_entities() + register_post(self) + return{ + "id_post": valid_post_id(self)['id_post'], + "content": "Comentario me ofendeu", + "offensive": True, + "prejudice": False, + "unrelated": False, + "others": False + } + +def register_report(self, report=None, headers=None): + if headers is None: + headers = self.create_student_token() + if report is None: + report = valid_report(self) + + return self.client.post(url_for('restapi.reportlist'), json=report, headers=headers) + + +class TestReportList(TestFlaskBase): + + def test_api_must_register_a_valid_report(self): + report = valid_report(self) + response = register_report(self, report=report) + self.assertEqual(response.status_code, 201) + self.assertEqual(response.json.get('message'), 'Report successfully added') + + def test_api_must_register_report_by_professor(self): + report = valid_report(self) + token = self.create_professor_token() + response = register_report(self, report=report, headers=token) + + self.assertEqual(response.status_code, 201) + self.assertEqual(response.json.get('message'), 'Report successfully added') + + def test_api_must_validate_no_token(self): + report = valid_report(self) + response = register_report(self, report=report, headers={}) + + self.assertEqual(response.status_code, 401) + self.assertEqual(response.json.get('msg'), 'Missing Authorization Header') + + def test_api_must_validate_empty_attributes(self): + report = {} + response = register_report(self, report=report) + + expected_json_keys = ['content', 'id_post', 'offensive', 'others', 'prejudice', 'unrelated'] + json_keys = list(response.json.keys()) + self.assertEqual(response.status_code, 400) + self.assertEqual(json_keys, expected_json_keys) + + def test_api_must_validate_attributes_min(self): + report = valid_report(self) + report['content'] = "" + response = register_report(self, report=report) + self.assertEqual(response.status_code, 400) + self.assertIsNotNone(response.json.get('content')) + + def test_api_must_validate_attributes_max(self): + report = valid_report(self) + report['content'] = "a"*121 + response = register_report(self, report=report) + self.assertEqual(response.status_code, 400) + self.assertIsNotNone(response.json.get('content')) + + def test_api_must_validate_post_relationship_not_found(self): + report = valid_report(self) + report['id_post']+= 1 + response = register_report(self, report=report) + + self.assertEqual(response.status_code, 404) + self.assertEqual(response.json.get('message'), "Post not found!") + + diff --git a/tests/tests_student.py b/tests/tests_student.py index eb097442..bb89b3a5 100644 --- a/tests/tests_student.py +++ b/tests/tests_student.py @@ -3,6 +3,7 @@ from app.model import student from app.model import post from tests_post import register_post, register_post_agree, register_post_disagree +from tests_report import register_report def valid_student(self): @@ -211,3 +212,13 @@ def test_must_delete_student_posts_disagrees(self): self.student['reg_student'], self.create_student_token()) self.assertEqual(response.status_code, 204) + + def test_must_delete_student_posts_reports(self): + self.create_base_student() + register_post(self) + register_report(self) + response = self.delete( + self.student['reg_student'], self.create_student_token()) + status = response.status_code + + self.assertEqual(response.status_code, 204)