From 616bd936f28a787c6539036335c0575ff6f6441d Mon Sep 17 00:00:00 2001 From: Menina294 <58502374+Menina294@users.noreply.github.com> Date: Mon, 1 Jun 2020 21:41:45 -0700 Subject: [PATCH] docs: update README file (#3) * Add the README file * made changes to README * added suggested changes * docs: Move lines #8 and #10 * moved README outside .github * remove extra README file Fix pylint score update requirements.txt for pylint modified per review request and added travis tests move travis --- .pylintrc | 3 + .travis.yml | 25 ++ README.md | 27 ++ app/api/bit_extension.py | 2 - app/api/dao/user_extension.py | 4 +- app/api/jwt_extension.py | 6 +- app/api/models/{user_extension.py => user.py} | 3 +- app/api/ms_api_utils.py | 40 +- app/api/resources/users.py | 32 +- app/database/db_add_mock.py | 348 ++++++++++-------- app/database/db_types/JsonCustomType.py | 12 +- .../mentorship_relation_extension.py | 17 +- .../models/bit_schema/organization.py | 3 +- .../models/bit_schema/personal_background.py | 32 +- app/database/models/bit_schema/program.py | 26 +- .../models/bit_schema/user_extension.py | 18 +- .../models/ms_schema/mentorship_relation.py | 5 +- app/database/models/ms_schema/tasks_list.py | 42 +-- app/database/models/ms_schema/user.py | 17 +- app/database/sqlalchemy_extension.py | 18 +- app/messages.py | 11 +- app/utils/bitschema_utils.py | 30 +- app/utils/decorator_utils.py | 5 +- app/utils/enum_utils.py | 3 - app/utils/validation_utils.py | 34 +- config.py | 19 +- migrations/env.py | 4 +- requirements.txt | 16 +- run.py | 39 +- tests/__init__.py | 0 tests/base_test_case.py | 39 ++ tests/test_app_config.py | 128 +++++++ tests/test_data.py | 95 +++++ tests/test_utils.py | 22 ++ 34 files changed, 775 insertions(+), 350 deletions(-) create mode 100644 .pylintrc create mode 100644 .travis.yml create mode 100644 README.md rename app/api/models/{user_extension.py => user.py} (95%) create mode 100644 tests/__init__.py create mode 100644 tests/base_test_case.py create mode 100644 tests/test_app_config.py create mode 100644 tests/test_data.py create mode 100644 tests/test_utils.py diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..e4a4846 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,3 @@ +[MESSAGES CONTROL] +disable=missing-docstring, C0301, R0801, E203, E266, E501, W503, R0401, R0911, R0912, C0330, W0511, R0903, C0303, C0412, E0602, C0103, C0413, W0212, W0614, W0401, E1101, W0613, W0611, R0902, R0913, C0415 +select = B,C,E,F,W,T4,B9, \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..679c9cd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,25 @@ +language: python +sudo: required +python: + - '3.6' +cache: pip +services: + - postgresql +addons: + postgresql: '10' + apt: + packages: + - postgresql-10 + - postgresql-client-10 +env: + global: + - PGPORT=5432 +before_script: + - psql -c 'create database bit_schema_test;' -U postgres + - psql -c 'create schema bitschema;' -U postgres + - psql -c 'create schema test_schema;' -U postgres + - psql -c 'create schema test_schema_2;' -U postgres +install: + - pip3 install -r requirements.txt +script: + - python -m unittest discover tests -v \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c92ad80 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Bridge-In-Tech (backend) +Bridge-In-Tech is an application that allows industries/companies, mentors and students to actively collaborate to one another. + +This is the backend client of Bridge-In-Tech. + +## Contributing + +**This project is under active development** + + + +Please read our [Contributing Guidelines](.github/CONTRIBUTING.md), [Code of Conduct](.github/CODE_OF_CONDUCT.md) and [Reporting Guidelines](.github/REPORTING_GUIDELINES.md) thoroughly. + + +## Branches + +This repository has the following branches: +- **master**: This branch contains the deployment of the backend. +- **develop**: This contains the latest code. All the contributing PRs must be sent to this branch. + +## Contact + +If you have any questions or want to discuss something about this repo, feel free to join our [Zulip Community](http://anitab-org.zulipchat.com/)! If you are a new contributor, head over to this project's stream [#bridge-in-tech](https://anitab-org.zulipchat.com/#narrow/stream/237630-bridge-in-tech) on Zulip to see ongoing discussions. + +## License + +The project is licensed under the GNU General Public License v3.0. Learn more about it in the [LICENSE](LICENSE) file. \ No newline at end of file diff --git a/app/api/bit_extension.py b/app/api/bit_extension.py index 3d0dcc6..38e3518 100644 --- a/app/api/bit_extension.py +++ b/app/api/bit_extension.py @@ -17,5 +17,3 @@ from app.api.resources.users import users_ns as user_namespace api.add_namespace(user_namespace, path="/") - - diff --git a/app/api/dao/user_extension.py b/app/api/dao/user_extension.py index 1ca4d8e..72d0a1b 100644 --- a/app/api/dao/user_extension.py +++ b/app/api/dao/user_extension.py @@ -1,6 +1,6 @@ from http import HTTPStatus -from typing import Dict -from sqlalchemy import func +# from typing import Dict +# from sqlalchemy import func from app.database.models.bit_schema.user_extension import UserExtensionModel from app import messages diff --git a/app/api/jwt_extension.py b/app/api/jwt_extension.py index 33b0aec..67c9f0d 100644 --- a/app/api/jwt_extension.py +++ b/app/api/jwt_extension.py @@ -1,5 +1,5 @@ -from flask_jwt_extended import JWTManager from http import HTTPStatus +from flask_jwt_extended import JWTManager from app import messages from app.api.bit_extension import api @@ -15,10 +15,10 @@ def my_expired_token_callback(): @jwt.invalid_token_loader -def my_invalid_token_callback(error_message): +def my_invalid_token_callback(): return messages.TOKEN_IS_INVALID, HTTPStatus.UNAUTHORIZED @jwt.unauthorized_loader -def my_unauthorized_request_callback(error_message): +def my_unauthorized_request_callback(): return messages.AUTHORISATION_TOKEN_IS_MISSING, HTTPStatus.UNAUTHORIZED diff --git a/app/api/models/user_extension.py b/app/api/models/user.py similarity index 95% rename from app/api/models/user_extension.py rename to app/api/models/user.py index 5345693..15b2c19 100644 --- a/app/api/models/user_extension.py +++ b/app/api/models/user.py @@ -1,9 +1,10 @@ from flask_restx import fields, Model -from app.utils.bitschema_utils import Timezone + def add_models_to_namespace(api_namespace): api_namespace.models[register_user_api_model.name] = register_user_api_model + register_user_api_model = Model( "User registration model", { diff --git a/app/api/ms_api_utils.py b/app/api/ms_api_utils.py index 32b4f71..b091264 100644 --- a/app/api/ms_api_utils.py +++ b/app/api/ms_api_utils.py @@ -1,10 +1,10 @@ -from flask import jsonify +import logging import requests + # from requests.exceptions import HTTPError from flask import json from werkzeug.exceptions import HTTPException -import logging # set base url @@ -14,45 +14,25 @@ # for ms-api heroku server # BASE_MS_API_URL = "https://bridge-in-tech-ms-test.herokuapp.com" -# @application.errorhandler(HTTPException) -# def handle_exception(e): -# """Return JSON instead of HTML for HTTP errors.""" -# # start with the correct headers and status code from the error -# response = e.get_response() -# # replace the body with JSON -# response.data = json.dumps({ -# "code": e.code, -# "name": e.name, -# "description": e.description, -# }) -# response.content_type = "application/json" -# return response # create instance def post_request(request_url, data): - response = None, + response = (None,) try: - + response_raw = requests.post( - request_url, - json = data, - headers = {"Accept": "application/json"} + request_url, json=data, headers={"Accept": "application/json"} ) response_raw.status_code = 201 response_raw.encoding = "utf-8" response = response_raw.json() - + except HTTPException as e: response = e.get_response() - response.data = json.dumps({ - "code": e.code, - "name": e.name, - "description": e.description, - }) + response.data = json.dumps( + {"code": e.code, "name": e.name, "description": e.description,} + ) response.content_type = "application/json" - print(f"{response}") + logging.warning(f"{response}") return response - - - diff --git a/app/api/resources/users.py b/app/api/resources/users.py index 75d1de3..3cb9c51 100644 --- a/app/api/resources/users.py +++ b/app/api/resources/users.py @@ -1,34 +1,40 @@ -from flask import request -from flask_restx import Resource, marshal, Namespace -from app.api.ms_api_utils import * -from app.api.dao.user_extension import UserExtensionDAO -from flask import json from http import HTTPStatus +from flask import request +from flask_restx import Resource, Namespace +from app.api.ms_api_utils import post_request, BASE_MS_API_URL +# from app.api.dao.user_extension import UserExtensionDAO from app import messages -from app.api.models.user_extension import * +from app.api.models.user import * users_ns = Namespace("Users", description="Operations related to users") add_models_to_namespace(users_ns) -DAO = UserExtensionDAO() +# DAO = UserExtensionDAO() + @users_ns.route("register") class UserRegister(Resource): @classmethod @users_ns.doc("create_user") - @users_ns.response(HTTPStatus.CREATED, "%s" % messages.USER_WAS_CREATED_SUCCESSFULLY) - @users_ns.response(HTTPStatus.BAD_REQUEST, "%s" % messages.PASSWORD_INPUT_BY_USER_HAS_INVALID_LENGTH) + @users_ns.response( + HTTPStatus.CREATED, "%s" % messages.USER_WAS_CREATED_SUCCESSFULLY + ) + @users_ns.response( + HTTPStatus.BAD_REQUEST, + "%s" % messages.PASSWORD_INPUT_BY_USER_HAS_INVALID_LENGTH, + ) @users_ns.response( HTTPStatus.CONFLICT, - "%s\n%s\n%s" + "%s\n%s" % ( messages.USER_USES_A_USERNAME_THAT_ALREADY_EXISTS, messages.USER_USES_AN_EMAIL_ID_THAT_ALREADY_EXISTS, ), ) - @users_ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "%s" % messages.INTERNAL_SERVER_ERROR) + @users_ns.response( + HTTPStatus.INTERNAL_SERVER_ERROR, "%s" % messages.INTERNAL_SERVER_ERROR + ) @users_ns.expect(register_user_api_model, validate=True) - def post(cls): """ Creates a new user. @@ -43,5 +49,3 @@ def post(cls): # send POST /register request to MS API and return response return post_request(f"{BASE_MS_API_URL}/register", data) - - diff --git a/app/database/db_add_mock.py b/app/database/db_add_mock.py index 91ee338..2d55f4d 100644 --- a/app/database/db_add_mock.py +++ b/app/database/db_add_mock.py @@ -1,21 +1,28 @@ +from datetime import datetime, timezone from app.database.sqlalchemy_extension import db from app.utils.bitschema_utils import * from app.utils.enum_utils import * -from datetime import datetime, timezone + def add_mock_data(): db.drop_all() from app.database.models.ms_schema.user import UserModel - from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel + from app.database.models.ms_schema.mentorship_relation import ( + MentorshipRelationModel, + ) from app.database.models.ms_schema.tasks_list import TasksListModel from app.database.models.ms_schema.task_comment import TaskCommentModel from app.database.models.bit_schema.organization import OrganizationModel from app.database.models.bit_schema.program import ProgramModel from app.database.models.bit_schema.user_extension import UserExtensionModel - from app.database.models.bit_schema.personal_background import PersonalBackgroundModel - from app.database.models.bit_schema.mentorship_relation_extension import MentorshipRelationExtensionModel + from app.database.models.bit_schema.personal_background import ( + PersonalBackgroundModel, + ) + from app.database.models.bit_schema.mentorship_relation_extension import ( + MentorshipRelationExtensionModel, + ) db.create_all() @@ -23,60 +30,68 @@ def add_mock_data(): # add user1 who is also an admin user1 = UserModel( - name = "testone", - username = "test0101", - password = "pbkdf2:sha256:50000$hY4PGrnp$b5c25743bc1308158d86b274af63e203ae4031061af5c7f9505c8420f50cae1d", - email = "rovexay139@prowerl.com", - terms_and_conditions_checked = True + name="testone", + username="test0101", + password="pbkdf2:sha256:50000$hY4PGrnp$b5c25743bc1308158d86b274af63e203ae4031061af5c7f9505c8420f50cae1d", + email="rovexay139@prowerl.com", + terms_and_conditions_checked=True, ) user1.available_to_mentor = True user1.need_mentoring = True - user1.registration_date = 1589151600.93296 # Sunday, 10 May 2020 11:00:00.932 PM UTC+0 + user1.registration_date = ( + 1589151600.93296 # Sunday, 10 May 2020 11:00:00.932 PM UTC+0 + ) user1.is_admin = True user1.is_email_verified = True user1.email_verification_date = "2020-05-11 09:39:37.950152" # add user2 user2 = UserModel( - name = "testtwo", - username = "test0202", - password = "pbkdf2:sha256:50000$4CtuxCwF$8b6584ce767ba0d70312d285ea8013a0ef9480b55c1873f4376809761095c7d8", - email = "povey55047@whowlft.com", - terms_and_conditions_checked = True + name="testtwo", + username="test0202", + password="pbkdf2:sha256:50000$4CtuxCwF$8b6584ce767ba0d70312d285ea8013a0ef9480b55c1873f4376809761095c7d8", + email="povey55047@whowlft.com", + terms_and_conditions_checked=True, ) user2.available_to_mentor = True user2.need_mentoring = True - user2.registration_date = 1589238000.95326 # Monday, 11 May 2020 11:00:00.953 PM UTC+0 + user2.registration_date = ( + 1589238000.95326 # Monday, 11 May 2020 11:00:00.953 PM UTC+0 + ) user1.is_admin = False user2.is_email_verified = True user2.email_verification_date = "2020-05-12 11:04:46.368948" # add user3 user3 = UserModel( - name = "testthree", - username = "test0303", - password = "pbkdf2:sha256:50000$gGcSwNwu$1dba66ff19891770113f2ae4b1af003fd1ee5a2005af7c2f6654663ff03a281e", - email = "nohor47235@ximtyl.com", - terms_and_conditions_checked = True + name="testthree", + username="test0303", + password="pbkdf2:sha256:50000$gGcSwNwu$1dba66ff19891770113f2ae4b1af003fd1ee5a2005af7c2f6654663ff03a281e", + email="nohor47235@ximtyl.com", + terms_and_conditions_checked=True, ) user3.available_to_mentor = True user3.need_mentoring = False - user3.registration_date = 1589410800.82208 # Wednesday, 13 May 2020 11:00:00.822 PM UTC+0 + user3.registration_date = ( + 1589410800.82208 # Wednesday, 13 May 2020 11:00:00.822 PM UTC+0 + ) user3.is_admin = False user3.is_email_verified = True - user3.email_verification_date = "2020-05-14 15:12:49.585829" + user3.email_verification_date = "2020-05-14 15:12:49.585829" # add user4 user4 = UserModel( - name = "testfour", - username = "test0404", - password = "pbkdf2:sha256:50000$6zulJGqT$ea4d6f539654e49d7af38672798e0ec673beb4e7d70660ba6e884fd56d30c062", - email = "yeroy74921@whowlft.com", - terms_and_conditions_checked = True + name="testfour", + username="test0404", + password="pbkdf2:sha256:50000$6zulJGqT$ea4d6f539654e49d7af38672798e0ec673beb4e7d70660ba6e884fd56d30c062", + email="yeroy74921@whowlft.com", + terms_and_conditions_checked=True, ) user4.available_to_mentor = False user4.need_mentoring = True - user4.registration_date = 1589371200.61836 # Wednesday, 13 May 2020 12:00:00.618 PM UTC+0 + user4.registration_date = ( + 1589371200.61836 # Wednesday, 13 May 2020 12:00:00.618 PM UTC+0 + ) user4.is_admin = False user4.is_email_verified = False @@ -86,42 +101,44 @@ def add_mock_data(): db.session.add(user3) db.session.add(user4) - # save to users table - db.session.commit() + # save to users table + db.session.commit() # for users_extension dummy data # user1 users_extension user1_extension = UserExtensionModel( - user_id = user1.id, - is_organization_rep = True, - timezone = Timezone.AUSTRALIAN_EASTERN_STANDARD_TIME + user_id=user1.id, + is_organization_rep=True, + timezone=Timezone.AUSTRALIAN_EASTERN_STANDARD_TIME, ) user1_extension.additional_info = {"phone": "03-88887777"} # user2 users_extension user2_extension = UserExtensionModel( - user_id = user2.id, - is_organization_rep = False, - timezone = Timezone.ALASKA_STANDARD_TIME + user_id=user2.id, + is_organization_rep=False, + timezone=Timezone.ALASKA_STANDARD_TIME, ) user2_extension.additional_info = { - "phone": "2130-99-11-99", "personal_website": "testtwo@github.io"} + "phone": "2130-99-11-99", + "personal_website": "testtwo@github.io", + } # user3 users_extension user3_extension = UserExtensionModel( - user_id = user3.id, - is_organization_rep = True, - timezone = Timezone.CENTRAL_EUROPEAN_TIME + user_id=user3.id, + is_organization_rep=True, + timezone=Timezone.CENTRAL_EUROPEAN_TIME, ) user3_extension.additional_info = { - "mobile": "+44-5555-666-777", "personal_website": "testthree@github.io"} + "mobile": "+44-5555-666-777", + "personal_website": "testthree@github.io", + } # user4 users_extension. Not yet confirm their email. user4_extension = UserExtensionModel( - user_id = user4.id, - is_organization_rep = False, - timezone = Timezone.CHARLIE_TIME + user_id=user4.id, is_organization_rep=False, timezone=Timezone.CHARLIE_TIME ) # add users_extension data @@ -131,127 +148,129 @@ def add_mock_data(): db.session.add(user4_extension) # save to users_extension table - db.session.commit() + db.session.commit() # for personal_background dummy data # user1 personal_background user1_background = PersonalBackgroundModel( - user_id = user1.id, - gender = Gender.FEMALE, - age = Age.AGE_25_TO_34, - ethnicity = Ethnicity.CAUCASIAN, - sexual_orientation = SexualOrientation.LGBTIA, - religion = Religion.BUDDHISM, - physical_ability = PhysicalAbility.WITHOUT_DISABILITY, - mental_ability = MentalAbility.WITHOUT_DISORDER, - socio_economic = SocioEconomic.LOWER_MIDDLE, - highest_education = HighestEducation.BACHELOR, - years_of_experience = YearsOfExperience.UP_TO_10 + user_id=user1.id, + gender=Gender.FEMALE, + age=Age.AGE_25_TO_34, + ethnicity=Ethnicity.CAUCASIAN, + sexual_orientation=SexualOrientation.LGBTIA, + religion=Religion.BUDDHISM, + physical_ability=PhysicalAbility.WITHOUT_DISABILITY, + mental_ability=MentalAbility.WITHOUT_DISORDER, + socio_economic=SocioEconomic.LOWER_MIDDLE, + highest_education=HighestEducation.BACHELOR, + years_of_experience=YearsOfExperience.UP_TO_10, ) user1_background.is_public = True # user2 personal_background user2_background = PersonalBackgroundModel( - user_id = user2.id, - gender = Gender.OTHER, - age = Age.AGE_35_TO_44, - ethnicity = Ethnicity.ASIAN, - sexual_orientation = SexualOrientation.HETEROSEXUAL, - religion = Religion.OTHER, - physical_ability = PhysicalAbility.WITH_DISABILITY, - mental_ability = MentalAbility.WITHOUT_DISORDER, - socio_economic = SocioEconomic.BELOW_POVERTY, - highest_education = HighestEducation.HIGH_SCHOOL, - years_of_experience = YearsOfExperience.UP_TO_3 + user_id=user2.id, + gender=Gender.OTHER, + age=Age.AGE_35_TO_44, + ethnicity=Ethnicity.ASIAN, + sexual_orientation=SexualOrientation.HETEROSEXUAL, + religion=Religion.OTHER, + physical_ability=PhysicalAbility.WITH_DISABILITY, + mental_ability=MentalAbility.WITHOUT_DISORDER, + socio_economic=SocioEconomic.BELOW_POVERTY, + highest_education=HighestEducation.HIGH_SCHOOL, + years_of_experience=YearsOfExperience.UP_TO_3, ) user2_background.others = {"religion": "Daoism"} user2_background.is_public = True # user3 personal_background user3_background = PersonalBackgroundModel( - user_id = user3.id, - gender = Gender.DECLINED, - age = Age.DECLINED, - ethnicity = Ethnicity.DECLINED, - sexual_orientation = SexualOrientation.DECLINED, - religion = Religion.DECLINED, - physical_ability = PhysicalAbility.DECLINED, - mental_ability = MentalAbility.DECLINED, - socio_economic = SocioEconomic.DECLINED, - highest_education = HighestEducation.DECLINED, - years_of_experience = YearsOfExperience.DECLINED + user_id=user3.id, + gender=Gender.DECLINED, + age=Age.DECLINED, + ethnicity=Ethnicity.DECLINED, + sexual_orientation=SexualOrientation.DECLINED, + religion=Religion.DECLINED, + physical_ability=PhysicalAbility.DECLINED, + mental_ability=MentalAbility.DECLINED, + socio_economic=SocioEconomic.DECLINED, + highest_education=HighestEducation.DECLINED, + years_of_experience=YearsOfExperience.DECLINED, ) user3_background.is_public = False # user4 has no background data because email has yet to be verified - # add users background data + # add users background data db.session.add(user1_background) db.session.add(user2_background) db.session.add(user3_background) # save to personal_background table - db.session.commit() - + db.session.commit() + # for organizations dummy data # organization1 data organization1 = OrganizationModel( - rep_id = user1.id, - name = "ABC Pty Ltd", - email = "abc_pty_ltd@mail.com", - address = "506 Elizabeth St, Melbourne VIC 3000, Australia", - website = "abc_pty_ltd.com", - timezone = user1_extension.timezone + rep_id=user1.id, + name="ABC Pty Ltd", + email="abc_pty_ltd@mail.com", + address="506 Elizabeth St, Melbourne VIC 3000, Australia", + website="abc_pty_ltd.com", + timezone=user1_extension.timezone, ) organization1.status = OrganizationStatus.DRAFT - organization1.join_date = 1589284800 # Tuesday, 12 May 2020 12:00:00 PM UTC+0 + organization1.join_date = 1589284800 # Tuesday, 12 May 2020 12:00:00 PM UTC+0 # organization2 data organization2 = OrganizationModel( - rep_id = user3.id, - name = "BCD.Co", - email = "bdc_co@mail.com", - address = "Novalisstraße 10, 10115 Berlin, Germany", - website = "bcd_co.com", - timezone = user3_extension.timezone + rep_id=user3.id, + name="BCD.Co", + email="bdc_co@mail.com", + address="Novalisstraße 10, 10115 Berlin, Germany", + website="bcd_co.com", + timezone=user3_extension.timezone, ) organization2.rep_department = "IT Department" organization2.about = "This is about us..." organization2.phone = "+49-30-688364150" organization2.status = OrganizationStatus.PUBLISH - organization2.join_date = 1589544000 # Friday, 15 May 2020 12:00:00 PM UTC+0 + organization2.join_date = 1589544000 # Friday, 15 May 2020 12:00:00 PM UTC+0 - # add organizations data db.session.add(organization1) db.session.add(organization2) - + # save to organizations table - db.session.commit() + db.session.commit() # for programs dummy data # program1 data program1 = ProgramModel( - program_name = "Program A", - organization_id = organization1, - start_date = 1596236400, # Friday, 31 July 2020 11:00:00 PM UTC+0 - end_date = 1598828400, # Sunday, 30 August 2020 11:00:00 PM UTC+0 + program_name="Program A", + organization_id=organization1, + start_date=1596236400, # Friday, 31 July 2020 11:00:00 PM UTC+0 + end_date=1598828400, # Sunday, 30 August 2020 11:00:00 PM UTC+0 ) - program1.creation_date = 1589457600 # Thursday, 14 May 2020 12:00:00 PM UTC+0 + program1.creation_date = 1589457600 # Thursday, 14 May 2020 12:00:00 PM UTC+0 # program2 data program2 = ProgramModel( - program_name = "Program B", - organization_id = organization2, - start_date = 1590062400, # Thursday, 21 May 2020 12:00:00 PM UTC+0 - end_date = 1596186000, # Friday, 31 July 2020 9:00:00 AM UTC+0 + program_name="Program B", + organization_id=organization2, + start_date=1590062400, # Thursday, 21 May 2020 12:00:00 PM UTC+0 + end_date=1596186000, # Friday, 31 July 2020 9:00:00 AM UTC+0 ) program2.description = "This is program B description..." program2.target_skills = ["Python", "PostgreSQL", "ReactJS"] - program2.target_candidate = {"gender": Gender.FEMALE.value, "age": Age.AGE_45_TO_54.value} + program2.target_candidate = { + "gender": Gender.FEMALE.value, + "age": Age.AGE_45_TO_54.value, + } program2.payment_amount = 2500.00 program2.payment_currency = "GBP" program2.contact_type = ContactType.FACE_TO_FACE @@ -272,18 +291,21 @@ def add_mock_data(): program2.irc_channel = "bcd_co@zulip.chat" program2.tags = program2.target_skills program2.status = ProgramStatus.IN_PROGRESS - program2.creation_date = 1589544000 # Friday, 15 May 2020 12:00:00 PM UTC+0 - + program2.creation_date = 1589544000 # Friday, 15 May 2020 12:00:00 PM UTC+0 + # program3 data program3 = ProgramModel( - program_name = "Program C", - organization_id = organization2, - start_date = 1594814400, # Wednesday, 15 July 2020 12:00:00 PM UTC+0 - end_date = 1598875200, # Monday, 31 August 2020 12:00:00 PM UTC+0 + program_name="Program C", + organization_id=organization2, + start_date=1594814400, # Wednesday, 15 July 2020 12:00:00 PM UTC+0 + end_date=1598875200, # Monday, 31 August 2020 12:00:00 PM UTC+0 ) program3.description = "This is program C description..." program3.target_skills = ["Dart", "Firebase", "Flutter"] - program3.target_candidate = {"physical_ability": PhysicalAbility.WITH_DISABILITY.value, "sexual_orientation": SexualOrientation.LGBTIA.value} + program3.target_candidate = { + "physical_ability": PhysicalAbility.WITH_DISABILITY.value, + "sexual_orientation": SexualOrientation.LGBTIA.value, + } program3.payment_amount = 3500.00 program3.payment_currency = "GBP" program3.contact_type = ContactType.BOTH @@ -304,16 +326,15 @@ def add_mock_data(): program3.irc_channel = "bcd_co@zulip.chat" program3.tags = program3.target_skills program3.status = ProgramStatus.OPEN - program3.creation_date = 1589630400 # Saturday, 16 May 2020 12:00:00 PM UTC+0 - + program3.creation_date = 1589630400 # Saturday, 16 May 2020 12:00:00 PM UTC+0 # add programs data db.session.add(program1) db.session.add(program2) db.session.add(program3) - + # save to programs table - db.session.commit() + db.session.commit() # for mentorship_relations dummy data @@ -327,36 +348,39 @@ def add_mock_data(): # create mentorship_relation1 when program sending request to mentor mentorship_relation1 = MentorshipRelationModel( - action_user_id = organization2.rep_id, - mentor_user = user1, - mentee_user = None, - creation_date = 1589630400, # Saturday, 16 May 2020 12:00:00 PM UTC+0 - end_date = program2.end_date, # Friday, 31 July 2020 9:00:00 AM UTC+0 == program2 end_date - state= MentorshipRelationState.PENDING, - notes = "Please be a mentor...", - tasks_list = tasks_list_1, + action_user_id=organization2.rep_id, + mentor_user=user1, + mentee_user=None, + creation_date=1589630400, # Saturday, 16 May 2020 12:00:00 PM UTC+0 + end_date=program2.end_date, # Friday, 31 July 2020 9:00:00 AM UTC+0 == program2 end_date + state=MentorshipRelationState.PENDING, + notes="Please be a mentor...", + tasks_list=tasks_list_1, ) - mentorship_relation1.start_date = program2.start_date # Thursday, 21 May 2020 12:00:00 PM UTC+0 + mentorship_relation1.start_date = ( + program2.start_date + ) # Thursday, 21 May 2020 12:00:00 PM UTC+0 db.session.add(mentorship_relation1) db.session.commit() - # initiate mentorship_relations_extension mentorship_relations_extension1 = MentorshipRelationExtensionModel( - program_id = program2.id, - mentorship_relation_id = mentorship_relation1.id + program_id=program2.id, mentorship_relation_id=mentorship_relation1.id + ) + mentorship_relations_extension1.mentor_request_date = ( + mentorship_relation1.creation_date ) - mentorship_relations_extension1.mentor_request_date = mentorship_relation1.creation_date db.session.add(mentorship_relations_extension1) db.session.commit() - # later, mentor accepted program request mentorship_relation1.action_id = user1.id mentorship_relation1.notes = "ok, will do." - mentorship_relations_extension1.mentor_agreed_date = 1589803200 # Monday, 18 May 2020 12:00:00 PM UTC+0 + mentorship_relations_extension1.mentor_agreed_date = ( + 1589803200 # Monday, 18 May 2020 12:00:00 PM UTC+0 + ) # update related tables db.session.add(mentorship_relation1) db.session.add(mentorship_relations_extension1) @@ -366,7 +390,9 @@ def add_mock_data(): mentorship_relation1.action_id = organization2.rep_id mentorship_relation1.mentee_id = user2.id mentorship_relation1.notes = "You're invited to work with us as a mentee." - mentorship_relations_extension1.mentee_request_date = 1589803200 # Monday, 18 May 2020 12:00:00 PM UTC+0 + mentorship_relations_extension1.mentee_request_date = ( + 1589803200 # Monday, 18 May 2020 12:00:00 PM UTC+0 + ) # update related tables db.session.add(mentorship_relation1) db.session.add(mentorship_relations_extension1) @@ -375,10 +401,14 @@ def add_mock_data(): # mentee accepted program request mentorship_relation1.action_id = user2.id mentorship_relation1.notes = "sure, why not." - mentorship_relations_extension1.mentee_agreed_date = 1589976000 # Wednesday, 20 May 2020 12:00:00 PM UTC+0 + mentorship_relations_extension1.mentee_agreed_date = ( + 1589976000 # Wednesday, 20 May 2020 12:00:00 PM UTC+0 + ) # update mentorship_relation state mentorship_relation1.state = MentorshipRelationState.ACCEPTED - mentorship_relation1.accept_date = mentorship_relations_extension1.mentee_agreed_date + mentorship_relation1.accept_date = ( + mentorship_relations_extension1.mentee_agreed_date + ) # update program status program2.status = ProgramStatus.IN_PROGRESS @@ -392,49 +422,55 @@ def add_mock_data(): tasks_list_1_task_a = "this is task a for tasks list 1" tasks_list_1_task_b = "this is task b for tasks list 1" - tasks_list_1.add_task(description=tasks_list_1_task_a, created_at=1590062400) # Thursday, 21 May 2020 12:00:00 PM UTC+0 - tasks_list_1.add_task(description=tasks_list_1_task_b, created_at=1590062400) # Thursday, 21 May 2020 12:00:00 PM UTC+0 - - + tasks_list_1.add_task( + description=tasks_list_1_task_a, created_at=1590062400 + ) # Thursday, 21 May 2020 12:00:00 PM UTC+0 + tasks_list_1.add_task( + description=tasks_list_1_task_b, created_at=1590062400 + ) # Thursday, 21 May 2020 12:00:00 PM UTC+0 + db.session.add(tasks_list_1) db.session.commit() # mentor comment on task a tasks_list_1_task_comment_a = TaskCommentModel( - user_id = user1.id, - task_id = 1, - relation_id = 1, - comment = "Do you need help with the task?" + user_id=user1.id, + task_id=1, + relation_id=1, + comment="Do you need help with the task?", + ) + tasks_list_1_task_comment_a.creation_date = ( + 1590062400 # Thursday, 21 May 2020 12:00:00 PM UTC+0 == tasks a creation date ) - tasks_list_1_task_comment_a.creation_date = 1590062400 # Thursday, 21 May 2020 12:00:00 PM UTC+0 == tasks a creation date db.session.add(tasks_list_1_task_comment_a) db.session.commit() - # mentee responded to mentor comment tasks_list_1_task_comment_a.user_id = user2.id tasks_list_1_task_comment_a.comment = "Nope. All good" - tasks_list_1_task_comment_a.modification_date = 1590148800 # Friday, 22 May 2020 12:00:00 PM UTC+0 + tasks_list_1_task_comment_a.modification_date = ( + 1590148800 # Friday, 22 May 2020 12:00:00 PM UTC+0 + ) db.session.add(tasks_list_1_task_comment_a) db.session.commit() - # when task a completed + # when task a completed tasks_list_1.update_task( - task_id = 1, - is_done = True, - completed_at = 1590235200, # Saturday, 23 May 2020 12:00:00 PM UTC+0 + task_id=1, + is_done=True, + completed_at=1590235200, # Saturday, 23 May 2020 12:00:00 PM UTC+0 ) # mentor add comment on task a completion tasks_list_1_task_comment_a.user_id = user1.id tasks_list_1_task_comment_a.comment = "Well done!" - tasks_list_1_task_comment_a.modification_date = 1590235200 # Saturday, 23 May 2020 12:00:00 PM UTC+0 + tasks_list_1_task_comment_a.modification_date = ( + 1590235200 # Saturday, 23 May 2020 12:00:00 PM UTC+0 + ) db.session.add(tasks_list_1) db.session.add(tasks_list_1_task_comment_a) db.session.commit() - - \ No newline at end of file diff --git a/app/database/db_types/JsonCustomType.py b/app/database/db_types/JsonCustomType.py index 1f9ed05..747144d 100644 --- a/app/database/db_types/JsonCustomType.py +++ b/app/database/db_types/JsonCustomType.py @@ -11,15 +11,13 @@ class JsonCustomType(db.TypeDecorator): def process_bind_param(cls, value, dialect): if value is None: return "{}" - else: - return json.dumps(value) + return json.dumps(value) @classmethod def process_result_value(cls, value, dialect): if value is None: return {} - else: - try: - return json.loads(value) - except (ValueError, TypeError): - return None + try: + return json.loads(value) + except (ValueError, TypeError): + return None diff --git a/app/database/models/bit_schema/mentorship_relation_extension.py b/app/database/models/bit_schema/mentorship_relation_extension.py index 66a25c1..7c19033 100644 --- a/app/database/models/bit_schema/mentorship_relation_extension.py +++ b/app/database/models/bit_schema/mentorship_relation_extension.py @@ -3,6 +3,7 @@ from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel from app.database.sqlalchemy_extension import db + class MentorshipRelationExtensionModel(db.Model): """Defines attibutes of mentorship relation that are specific only to BridgeInTech. @@ -18,8 +19,18 @@ class MentorshipRelationExtensionModel(db.Model): id = db.Column(db.Integer, primary_key=True) - program_id = db.Column(db.Integer, db.ForeignKey("bitschema.programs.id", ondelete="CASCADE"), nullable=False, unique=True) - mentorship_relation_id = db.Column(db.Integer, db.ForeignKey("public.mentorship_relations.id", ondelete="CASCADE"), nullable=False, unique=True) + program_id = db.Column( + db.Integer, + db.ForeignKey("bitschema.programs.id", ondelete="CASCADE"), + nullable=False, + unique=True, + ) + mentorship_relation_id = db.Column( + db.Integer, + db.ForeignKey("public.mentorship_relations.id", ondelete="CASCADE"), + nullable=False, + unique=True, + ) mentor_request_date = db.Column(db.Numeric("16,6", asdecimal=False)) mentor_agreed_date = db.Column(db.Numeric("16,6", asdecimal=False)) mentee_request_date = db.Column(db.Numeric("16,6", asdecimal=False)) @@ -55,7 +66,7 @@ def find_by_id(cls, _id) -> "MentorshipRelationExtensionModel": _id: The id of a mentorship_relations_extension. """ return cls.query.filter_by(id=_id).first() - + def save_to_db(self) -> None: """Saves the model to the database.""" db.session.add(self) diff --git a/app/database/models/bit_schema/organization.py b/app/database/models/bit_schema/organization.py index 8de8a27..295e35c 100644 --- a/app/database/models/bit_schema/organization.py +++ b/app/database/models/bit_schema/organization.py @@ -1,8 +1,8 @@ import time +from sqlalchemy import null from app.database.sqlalchemy_extension import db from app.utils.bitschema_utils import OrganizationStatus, Timezone from app.database.models.bit_schema.program import ProgramModel -from sqlalchemy import null class OrganizationModel(db.Model): @@ -57,7 +57,6 @@ def __init__(self, rep_id, name, email, address, website, timezone): # default values self.status = OrganizationStatus.DRAFT self.join_date = time.time() - def json(self): """Returns OrganizationModel object in json format.""" diff --git a/app/database/models/bit_schema/personal_background.py b/app/database/models/bit_schema/personal_background.py index 574383f..17b34cd 100644 --- a/app/database/models/bit_schema/personal_background.py +++ b/app/database/models/bit_schema/personal_background.py @@ -1,7 +1,7 @@ +from sqlalchemy import null +from sqlalchemy.dialects.postgresql import JSONB from app.database.sqlalchemy_extension import db from app.utils.bitschema_utils import * -from sqlalchemy.dialects.postgresql import JSONB -from sqlalchemy import null class PersonalBackgroundModel(db.Model): @@ -30,7 +30,12 @@ class PersonalBackgroundModel(db.Model): id = db.Column(db.Integer, primary_key=True) # User's personal background data - user_id = db.Column(db.Integer, db.ForeignKey("public.users.id", ondelete="CASCADE"), nullable=False, unique=True) + user_id = db.Column( + db.Integer, + db.ForeignKey("public.users.id", ondelete="CASCADE"), + nullable=False, + unique=True, + ) gender = db.Column(db.Enum(Gender)) age = db.Column(db.Enum(Age)) ethnicity = db.Column(db.Enum(Ethnicity)) @@ -44,11 +49,24 @@ class PersonalBackgroundModel(db.Model): others = db.Column(JSONB(none_as_null=False), default=JSONB.NULL) is_public = db.Column(db.Boolean) - def __init__(self, user_id, gender, age, ethnicity, sexual_orientation, religion, physical_ability, mental_ability, socio_economic, highest_education, years_of_experience): + def __init__( + self, + user_id, + gender, + age, + ethnicity, + sexual_orientation, + religion, + physical_ability, + mental_ability, + socio_economic, + highest_education, + years_of_experience, + ): """Initialises PersonalBackgroundModel class.""" ## required fields self.user_id = user_id - self.gender = gender + self.gender = gender self.age = age self.ethnicity = ethnicity self.sexual_orientation = sexual_orientation @@ -58,11 +76,10 @@ def __init__(self, user_id, gender, age, ethnicity, sexual_orientation, religion self.socio_economic = socio_economic self.highest_education = highest_education self.years_of_experience = years_of_experience - + # default values self.others = None self.is_public = False - def json(self): """Returns PersonalBackgroundModel object in json format.""" @@ -106,7 +123,6 @@ def find_by_id(cls, user_id) -> "PersonalBackgroundModel": _id: The id of a user. """ return cls.query.filter_by(user_id=user_id).first() - def save_to_db(self) -> None: """Adds user's personal background to the database. """ diff --git a/app/database/models/bit_schema/program.py b/app/database/models/bit_schema/program.py index 0236d79..f8fdde7 100644 --- a/app/database/models/bit_schema/program.py +++ b/app/database/models/bit_schema/program.py @@ -1,12 +1,13 @@ -from app.database.sqlalchemy_extension import db import time -# from datetime import datetime -from app.utils.bitschema_utils import ContactType, Zone, ProgramStatus +from sqlalchemy import null from sqlalchemy import BigInteger, ARRAY -from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel from sqlalchemy.dialects.postgresql import JSONB -from sqlalchemy import null -from app.database.models.bit_schema.mentorship_relation_extension import MentorshipRelationExtensionModel +from app.database.sqlalchemy_extension import db +from app.utils.bitschema_utils import ContactType, Zone, ProgramStatus +# from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel +from app.database.models.bit_schema.mentorship_relation_extension import ( + MentorshipRelationExtensionModel, +) class ProgramModel(db.Model): @@ -26,7 +27,11 @@ class ProgramModel(db.Model): id = db.Column(db.Integer, primary_key=True) program_name = db.Column(db.String(100), unique=True, nullable=False) - organization_id = db.Column(db.Integer, db.ForeignKey("bitschema.organizations.id", ondelete="CASCADE"), nullable=False) + organization_id = db.Column( + db.Integer, + db.ForeignKey("bitschema.organizations.id", ondelete="CASCADE"), + nullable=False, + ) start_date = db.Column(db.Numeric("16,6", asdecimal=False)) end_date = db.Column(db.Numeric("16,6", asdecimal=False)) description = db.Column(db.String(500)) @@ -68,13 +73,12 @@ def __init__(self, program_name, organization_id, start_date, end_date): self.organization = organization_id self.start_date = start_date self.end_date = end_date - + # default value self.target_candidate = None self.status = ProgramStatus.DRAFT self.creation_date = time.time() - - + def json(self): """Returns ProgramModel object in json format.""" return { @@ -150,4 +154,4 @@ def save_to_db(self) -> None: def delete_from_db(self) -> None: """Deletes a program from the database. """ db.session.delete(self) - db.session.commit() \ No newline at end of file + db.session.commit() diff --git a/app/database/models/bit_schema/user_extension.py b/app/database/models/bit_schema/user_extension.py index fd640e0..090473b 100644 --- a/app/database/models/bit_schema/user_extension.py +++ b/app/database/models/bit_schema/user_extension.py @@ -1,6 +1,6 @@ -from app.database.sqlalchemy_extension import db -from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy import null +from sqlalchemy.dialects.postgresql import JSONB +from app.database.sqlalchemy_extension import db from app.utils.bitschema_utils import Timezone @@ -13,18 +13,22 @@ class UserExtensionModel(db.Model): timezone: A string for storing user timezone information. """ - # Specifying database table used for UserExtensionModel + # Specifying database table used for UserExtensionModel __tablename__ = "users_extension" __table_args__ = {"schema": "bitschema", "extend_existing": True} id = db.Column(db.Integer, primary_key=True) - user_id = db.Column(db.Integer, db.ForeignKey("public.users.id", ondelete="CASCADE"), nullable=False, unique=True) + user_id = db.Column( + db.Integer, + db.ForeignKey("public.users.id", ondelete="CASCADE"), + nullable=False, + unique=True, + ) is_organization_rep = db.Column(db.Boolean) additional_info = db.Column(JSONB(none_as_null=False), default=JSONB.NULL) timezone = db.Column(db.Enum(Timezone)) - """Initialises UserExtensionModel class.""" ## required fields def __init__(self, user_id, is_organization_rep, timezone): @@ -53,7 +57,7 @@ def __repr__(self): f"User's as organization representative is: {self.is_organization_rep}\n" f"User's timezone is: {self.timezone}\n" ) - + @classmethod def find_by_user_id(cls, user_id) -> "UserExtensionModel": @@ -62,7 +66,7 @@ def find_by_user_id(cls, user_id) -> "UserExtensionModel": _id: The id of a user. """ return cls.query.filter_by(user_id=user_id).first() - + def save_to_db(self) -> None: """Adds user's BridgeInTech specific data to the database. """ db.session.add(self) diff --git a/app/database/models/ms_schema/mentorship_relation.py b/app/database/models/ms_schema/mentorship_relation.py index 8c48eb2..9217f72 100644 --- a/app/database/models/ms_schema/mentorship_relation.py +++ b/app/database/models/ms_schema/mentorship_relation.py @@ -112,10 +112,7 @@ def json(self): "notes": self.notes, } - # def __repr__(self): - # return "Mentorship Relation with id = %s, Mentor has id = %s and Mentee has id = %d" \ - # % (self.id, self.mentor_id, self.mentee_id) - + @classmethod def find_by_id(cls, _id) -> "MentorshipRelationModel": diff --git a/app/database/models/ms_schema/tasks_list.py b/app/database/models/ms_schema/tasks_list.py index acf6f8d..faae990 100644 --- a/app/database/models/ms_schema/tasks_list.py +++ b/app/database/models/ms_schema/tasks_list.py @@ -1,8 +1,7 @@ from enum import unique, Enum - +from datetime import date from app.database.db_types.JsonCustomType import JsonCustomType from app.database.sqlalchemy_extension import db -from datetime import date class TasksListModel(db.Model): @@ -31,15 +30,15 @@ def __init__(self, tasks: "TasksListModel" = None): A Value Error if the task is not initialized. """ - if tasks is None: + if not tasks: self.tasks = [] self.next_task_id = 1 else: if isinstance(tasks, list): self.tasks = [] - self.next_task_id = len(tasks) + 1 + self.next_task_id += 1 else: - raise ValueError(TypeError) + raise TypeError("task is not initialized") def add_task( self, description: str, created_at: date, is_done=False, completed_at=None @@ -69,10 +68,10 @@ def delete_task(self, task_id: int) -> None: Args: task_id: Id of the task to be deleted. """ - - new_list = list( - filter(lambda task: task[TasksFields.ID.value] != task_id, self.tasks) - ) + new_list = [] + for task in self.tasks: + if task[TasksFields.ID.value] != task_id: + new_list.append(task) self.tasks = new_list self.save_to_db() @@ -98,19 +97,19 @@ def update_task( for task in self.tasks: if task[TasksFields.ID.value] == task_id: new_task = task.copy() - if description is not None: + if not description: new_task[TasksFields.DESCRIPTION.value] = description - if is_done is not None: + if not is_done: new_task[TasksFields.IS_DONE.value] = is_done - if completed_at is not None: + if not completed_at: new_task[TasksFields.COMPLETED_AT.value] = completed_at - new_list = new_list + [new_task] + new_list += [new_task] continue - new_list = new_list + [task] + new_list += [task] self.tasks = new_list self.save_to_db() @@ -127,10 +126,9 @@ def find_task_by_id(self, task_id: int): task = list( filter(lambda task: task[TasksFields.ID.value] == task_id, self.tasks) ) - if len(task) == 0: + if not task: return None - else: - return task[0] + return task[0] def is_empty(self) -> bool: """Checks if the list of tasks is empty. @@ -139,7 +137,7 @@ def is_empty(self) -> bool: Boolean; True if the task is empty, False otherwise. """ - return len(self.tasks) == 0 + return self.tasks def json(self): """Creates json object of the attributes of list of tasks. @@ -162,10 +160,10 @@ def __repr__(self): A string representation of the task object. """ - return "Task | id = %s; tasks = %s; next task id = %s" % ( - self.id, - self.tasks, - self.next_task_id, + return ( + f"Task id is {self.id}\n" + f"Tasks list is {self.tasks}\n" + f"Next task id is {self.next_task_id}\n" ) @classmethod diff --git a/app/database/models/ms_schema/user.py b/app/database/models/ms_schema/user.py index 3a83fa1..6ba576e 100644 --- a/app/database/models/ms_schema/user.py +++ b/app/database/models/ms_schema/user.py @@ -1,10 +1,9 @@ +import time from typing import Optional - +from sqlalchemy import null +from sqlalchemy.types import JSON from werkzeug.security import generate_password_hash, check_password_hash -import time from app.database.sqlalchemy_extension import db -from sqlalchemy.types import JSON -from sqlalchemy import null from app.database.models.bit_schema.personal_background import PersonalBackgroundModel from app.database.models.bit_schema.organization import OrganizationModel from app.database.models.bit_schema.user_extension import UserExtensionModel @@ -103,8 +102,7 @@ def __init__(self, name, username, password, email, terms_and_conditions_checked # optional fields self.need_mentoring = False self.available_to_mentor = False - # self.is_company_rep = False - + def json(self): """Returns Usermodel object in json format.""" return { @@ -136,8 +134,11 @@ def json(self): def __repr__(self): """Returns the user's name and username. """ - return "User name %s. Username is %s ." % (self.name, self.username) - + return ( + f"User name is {self.name}\n" + f"User username is {self.username}\n" + ) + @classmethod def find_by_username(cls, username: str) -> "UserModel": """Returns the user that has the username we searched for. """ diff --git a/app/database/sqlalchemy_extension.py b/app/database/sqlalchemy_extension.py index ddac6ce..26942a3 100644 --- a/app/database/sqlalchemy_extension.py +++ b/app/database/sqlalchemy_extension.py @@ -2,10 +2,14 @@ from flask_sqlalchemy import SQLAlchemy from sqlalchemy import MetaData -db = SQLAlchemy(metadata=MetaData(naming_convention={ - 'pk': 'pk_%(table_name)s', - 'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s', - 'ix': 'ix_%(table_name)s_%(column_0_name)s', - 'uq': 'uq_%(table_name)s_%(column_0_name)s', - 'ck': 'ck_%(table_name)s_%(constraint_name)s', -})) +db = SQLAlchemy( + metadata=MetaData( + naming_convention={ + "pk": "pk_%(table_name)s", + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "ix": "ix_%(table_name)s_%(column_0_name)s", + "uq": "uq_%(table_name)s_%(column_0_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + } + ) +) diff --git a/app/messages.py b/app/messages.py index fc7c9d1..a65a232 100644 --- a/app/messages.py +++ b/app/messages.py @@ -1,4 +1,4 @@ -from app.api.validations.user import (PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH) +from app.api.validations.user import PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH # Invalid fields NAME_INPUT_BY_USER_IS_INVALID = {"message": "Your name is invalid."} @@ -11,7 +11,9 @@ FIELD_AVAILABLE_TO_MENTOR_IS_INVALID = { "message": "Field available_to_mentor" " is not valid." } -PASSWORD_INPUT_BY_USER_HAS_INVALID_LENGTH={"message": f"The password field has to be longer than {PASSWORD_MIN_LENGTH} characters and shorter than {PASSWORD_MAX_LENGTH} characters."} +PASSWORD_INPUT_BY_USER_HAS_INVALID_LENGTH = { + "message": f"The password field has to be longer than {PASSWORD_MIN_LENGTH} characters and shorter than {PASSWORD_MAX_LENGTH} characters." +} # Not found MENTORSHIP_RELATION_REQUEST_DOES_NOT_EXIST = { @@ -284,4 +286,7 @@ "message": "Validation error. End date represented by the timestamp is invalid." } NOT_IMPLEMENTED = {"message": "Not implemented."} -INTERNAL_SERVER_ERROR = {"message": "An unexpected server error occurs while processing your request. Please try again later."} \ No newline at end of file +INTERNAL_SERVER_ERROR = { + "message": "An unexpected server error occurs while processing your request. Please try again later." +} + diff --git a/app/utils/bitschema_utils.py b/app/utils/bitschema_utils.py index 4fc23e3..fad1643 100644 --- a/app/utils/bitschema_utils.py +++ b/app/utils/bitschema_utils.py @@ -1,7 +1,9 @@ from enum import Enum, unique + # from sqlalchemy import Enum # from sqlalchemy.dialects.postgresql import ENUM + @unique class ProgramStatus(Enum): DRAFT = "Draft" @@ -13,6 +15,7 @@ class ProgramStatus(Enum): def programStatus(self): return list(map(str, self)) + @unique class OrganizationStatus(Enum): DRAFT = "Draft" @@ -22,6 +25,7 @@ class OrganizationStatus(Enum): def OrganizationStatus(self): return list(map(str, self)) + @unique class Gender(Enum): FEMALE = "Female" @@ -33,6 +37,7 @@ class Gender(Enum): def gender(self): return list(map(str, self)) + @unique class Age(Enum): UNDER_18 = "Under 18" @@ -49,6 +54,7 @@ class Age(Enum): def age(self): return list(map(str, self)) + @unique class Ethnicity(Enum): AFRICAN_AMERICAN = "African-American/Black" @@ -64,6 +70,7 @@ class Ethnicity(Enum): def ethnicity(self): return list(map(str, self)) + @unique class SexualOrientation(Enum): HETEROSEXUAL = "Heterosexual/Straight" @@ -75,6 +82,7 @@ class SexualOrientation(Enum): def sexualOrientation(self): return list(map(str, self)) + @unique class Religion(Enum): CHRISTIANITY = "Christianity" @@ -89,6 +97,7 @@ class Religion(Enum): def religion(self): return list(map(str, self)) + @unique class PhysicalAbility(Enum): WITH_DISABILITY = "With/had limited physical ability (or with/had some type of physical disability/ies)" @@ -99,6 +108,7 @@ class PhysicalAbility(Enum): def physicalAbility(self): return list(map(str, self)) + @unique class MentalAbility(Enum): WITH_DISORDER = "With/previously had some type of mental disorders" @@ -109,6 +119,7 @@ class MentalAbility(Enum): def mentalAbility(self): return list(map(str, self)) + @unique class SocioEconomic(Enum): UPPER = "Upper class/Elite" @@ -122,6 +133,7 @@ class SocioEconomic(Enum): def socioEconomic(self): return list(map(str, self)) + @unique class HighestEducation(Enum): BELOW_HIGH_SCHOOL = "Have/did not completed High School" @@ -137,6 +149,7 @@ class HighestEducation(Enum): def highestEducation(self): return list(map(str, self)) + @unique class YearsOfExperience(Enum): UNDER_ONE = "Less than a year" @@ -150,24 +163,27 @@ class YearsOfExperience(Enum): def yearsOfExperience(self): return list(map(str, self)) + @unique class ContactType(Enum): FACE_TO_FACE = "Face-to-face" REMOTE = "Remote" BOTH = "Both Remote and Face-to-face" - + def contactType(self): return list(map(str, self)) + @unique class Zone(Enum): - LOCAL = "Local", - NATIONAL = "National", - GLOBAL = "Global", + LOCAL = ("Local",) + NATIONAL = ("National",) + GLOBAL = ("Global",) def zone(self): return list(map(str, self)) + @unique class Timezone(Enum): CAPE_VERDE_TIME = "UTC-01:00/Cape Verde Time" @@ -192,11 +208,11 @@ class Timezone(Enum): INDIA_STANDARD_TIME = "UTC+05:30/India Standard Time" CHINA_STANDARD_TIME = "UTC+08:00/China Standard TIme" AUSTRALIAN_WESTERN_STANDARD_TIME = "UTC+08:00/Australian Western Standard Time" - AUSTRALIAN_CENTRAL_SOUTH_STANDARD_TIME = "UTC+09:30/Australian Central and South Standard Time" + AUSTRALIAN_CENTRAL_SOUTH_STANDARD_TIME = ( + "UTC+09:30/Australian Central and South Standard Time" + ) AUSTRALIAN_EASTERN_STANDARD_TIME = "UTC+10:00/Australian Eastern Standard Time" NEW_ZEALAND_STANDARD_TIME = "UTC+12:00/New Zealand Standard Time" - - def timezone(self): return list(map(str, self)) diff --git a/app/utils/decorator_utils.py b/app/utils/decorator_utils.py index 0105309..c0e26e4 100644 --- a/app/utils/decorator_utils.py +++ b/app/utils/decorator_utils.py @@ -1,8 +1,8 @@ """ This module is used to define decorators for the app """ -from app import messages from http import HTTPStatus +from app import messages from app.database.models.ms_schema.user import UserModel @@ -40,7 +40,6 @@ def check_verification(*args, **kwargs): HTTPStatus.FORBIDDEN, ) return user_function(*args, **kwargs) - else: - return messages.USER_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND + return messages.USER_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND return check_verification diff --git a/app/utils/enum_utils.py b/app/utils/enum_utils.py index 610bdd6..6536843 100644 --- a/app/utils/enum_utils.py +++ b/app/utils/enum_utils.py @@ -9,8 +9,5 @@ class MentorshipRelationState(IntEnum): CANCELLED = 4 COMPLETED = 5 - def values(self): return list(map(int, self)) - - diff --git a/app/utils/validation_utils.py b/app/utils/validation_utils.py index ffbc916..b04ce69 100644 --- a/app/utils/validation_utils.py +++ b/app/utils/validation_utils.py @@ -88,22 +88,22 @@ def validate_length(field_length, min_length, max_length, field_name): False, error_msg: if string input is either less than the minimum length, or more than the maximum length. True, {}: if string input is longer or equals to the minimum length, and less than or equals to the maximum length. """ - if not (min_length <= field_length <= max_length): + if not min_length <= field_length <= max_length: if min_length <= 0: error_msg = { "message": get_length_validation_error_message( field_name, None, max_length ) } - else: - error_msg = { - "message": get_length_validation_error_message( - field_name, min_length, max_length - ) - } + + error_msg = { + "message": get_length_validation_error_message( + field_name, min_length, max_length + ) + } return False, error_msg - else: - return True, {} + + return True, {} def get_length_validation_error_message(field_name, min_length, max_length): @@ -122,15 +122,15 @@ def get_length_validation_error_message(field_name, min_length, max_length): return "The {field_name} field has to be shorter than {max_limit} characters.".format( field_name=field_name, max_limit=max_length + 1 ) - else: - return ( - "The {field_name} field has to be longer than {min_limit} " - "characters and shorter than {max_limit} characters.".format( - field_name=field_name, - min_limit=min_length - 1, - max_limit=max_length + 1, - ) + + return ( + "The {field_name} field has to be longer than {min_limit} " + "characters and shorter than {max_limit} characters.".format( + field_name=field_name, + min_limit=min_length - 1, + max_limit=max_length + 1, ) + ) def get_stripped_string(string_with_whitespaces): diff --git a/config.py b/config.py index ae9490e..76734f1 100644 --- a/config.py +++ b/config.py @@ -73,11 +73,10 @@ class LocalConfig(BaseConfig): DEBUG = True # Using a local postgre database - # SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" - SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() + SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" + # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() class DevelopmentConfig(BaseConfig): - # SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') DEBUG = True # Using elephantsql - BridgeInTech remote db @@ -87,8 +86,7 @@ class DevelopmentConfig(BaseConfig): class TestingConfig(BaseConfig): TESTING = True MOCK_EMAIL = True - # SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_TEST_URL') - + # Using a local postgre database SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema_test" # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_test_uri() @@ -97,13 +95,14 @@ class StagingConfig(BaseConfig): """Staging configuration.""" DEBUG = True - SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() - MOCK_EMAIL = False + # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() + SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" + class ProductionConfig(BaseConfig): - # SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') - SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() - MOCK_EMAIL = False + # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() + SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" + def get_env_config() -> str: flask_config_name = os.getenv("FLASK_ENVIRONMENT_CONFIG", "dev") diff --git a/migrations/env.py b/migrations/env.py index 774bf93..0f7f4a5 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -30,9 +30,9 @@ ) import re -schema_names = re.split(r',\s*', "public,bitschema") +schema_names = re.split(r",\s*", "public,bitschema") -target_metadata = current_app.extensions['migrate'].db.metadata +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, diff --git a/requirements.txt b/requirements.txt index 88dbd64..54ca125 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,10 +3,10 @@ aniso8601==3.0.0 appdirs==1.4.3 APScheduler==3.5.1 asn1crypto==0.24.0 +astroid==2.4.1 attrs==19.3.0 awsebcli==3.14.1 bcrypt==3.1.7 -black==19.3b0 blessed==1.15.0 blinker==1.4 botocore==1.10.48 @@ -38,20 +38,25 @@ future==0.16.0 gunicorn==20.0.4 idna==2.6 importlib-metadata==1.6.0 +isort==4.3.21 itsdangerous==0.24 Jinja2==2.11.2 jmespath==0.9.3 jsonschema==2.6.0 +lazy-object-proxy==1.4.3 Mako==1.1.2 MarkupSafe==1.1.1 mccabe==0.6.1 paramiko==2.7.1 -pathspec==0.5.5 +pathspec==0.8.0 psycopg2-binary==2.8.3 -pycodestyle==2.5.0 +pycodestyle==2.6.0 pycparser==2.18 -pyflakes==2.1.1 +pyflakes==2.2.0 PyJWT==1.4.2 +pylint==2.5.2 +pylint-flask==0.6 +pylint-plugin-utils==0.6 PyMySQL==0.9.2 PyNaCl==1.3.0 pyrsistent==0.16.0 @@ -63,7 +68,7 @@ PyYAML==3.13 regex==2020.2.20 requests==2.18.4 semantic-version==2.5.0 -six==1.11.0 +six==1.15.0 SQLAlchemy==1.2.7 tabulate==0.7.5 termcolor==1.1.0 @@ -75,4 +80,5 @@ urllib3==1.22 wcwidth==0.1.7 websocket-client==0.48.0 Werkzeug==0.15.3 +wrapt==1.12.1 zipp==3.1.0 diff --git a/run.py b/run.py index fc0d83d..f1ee39e 100644 --- a/run.py +++ b/run.py @@ -1,11 +1,11 @@ import os from flask import Flask, jsonify + # from flask_restx import Resource, Api from config import get_env_config from flask_migrate import Migrate, MigrateCommand - def create_app(config_filename: str) -> Flask: # instantiate the app app = Flask(__name__, instance_relative_config=True) @@ -19,14 +19,20 @@ def create_app(config_filename: str) -> Flask: db.init_app(app) from app.database.models.ms_schema.user import UserModel - from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel + from app.database.models.ms_schema.mentorship_relation import ( + MentorshipRelationModel, + ) from app.database.models.ms_schema.tasks_list import TasksListModel from app.database.models.ms_schema.task_comment import TaskCommentModel from app.database.models.bit_schema.organization import OrganizationModel from app.database.models.bit_schema.program import ProgramModel from app.database.models.bit_schema.user_extension import UserExtensionModel - from app.database.models.bit_schema.personal_background import PersonalBackgroundModel - from app.database.models.bit_schema.mentorship_relation_extension import MentorshipRelationExtensionModel + from app.database.models.bit_schema.personal_background import ( + PersonalBackgroundModel, + ) + from app.database.models.bit_schema.mentorship_relation_extension import ( + MentorshipRelationExtensionModel, + ) migrate = Migrate(app, db) @@ -43,22 +49,30 @@ def create_app(config_filename: str) -> Flask: mail.init_app(app) return app - + + application = create_app(get_env_config()) + @application.before_first_request def create_tables(): from app.database.sqlalchemy_extension import db - + from app.database.models.ms_schema.user import UserModel - from app.database.models.ms_schema.mentorship_relation import MentorshipRelationModel + from app.database.models.ms_schema.mentorship_relation import ( + MentorshipRelationModel, + ) from app.database.models.ms_schema.tasks_list import TasksListModel from app.database.models.ms_schema.task_comment import TaskCommentModel from app.database.models.bit_schema.organization import OrganizationModel from app.database.models.bit_schema.program import ProgramModel from app.database.models.bit_schema.user_extension import UserExtensionModel - from app.database.models.bit_schema.personal_background import PersonalBackgroundModel - from app.database.models.bit_schema.mentorship_relation_extension import MentorshipRelationExtensionModel + from app.database.models.bit_schema.personal_background import ( + PersonalBackgroundModel, + ) + from app.database.models.bit_schema.mentorship_relation_extension import ( + MentorshipRelationExtensionModel, + ) # uncomment the line below if no dummy data needed on INITIAL setup! # Warning !!! Do not uncomment if this is not your INITIAL setup to database! @@ -67,11 +81,10 @@ def create_tables(): # uncomment lines below if you want to add dummy data on INITIAL setup! # !!! Warning!!! Treat this with caution as it will mess up your db!! # Warning !!! Do not uncomment if this is not your INITIAL setup to database! - + # from app.database.db_add_mock import add_mock_data # uncomment here # add_mock_data() - @application.shell_context_processor def make_shell_context(): return { @@ -88,7 +101,7 @@ def make_shell_context(): } # uncomment the lines below if you want to test querying database - + if __name__ == "__main__": - application.run(port=5000) \ No newline at end of file + application.run(port=5000) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/base_test_case.py b/tests/base_test_case.py new file mode 100644 index 0000000..b4d4be4 --- /dev/null +++ b/tests/base_test_case.py @@ -0,0 +1,39 @@ +from flask_testing import TestCase + +from app.database.models.ms_schema.user import UserModel +from run import application +from app.database.sqlalchemy_extension import db + +from tests.test_data import test_admin_user + + +class BaseTestCase(TestCase): + @classmethod + def create_app(cls): + application.config.from_object("config.TestingConfig") + + # Setting up test environment variables + application.config["SECRET_KEY"] = "TEST_SECRET_KEY" + application.config["SECURITY_PASSWORD_SALT"] = "TEST_SECURITY_PWD_SALT" + return application + + def setUp(self): + db.create_all() + + self.admin_user = UserModel( + name=test_admin_user["name"], + email=test_admin_user["email"], + username=test_admin_user["username"], + password=test_admin_user["password"], + terms_and_conditions_checked=test_admin_user[ + "terms_and_conditions_checked" + ], + ) + db.session.add(self.admin_user) + db.session.commit() + self.admin_user.is_email_verified = True + + @classmethod + def tearDown(cls): + db.session.remove() + db.drop_all() \ No newline at end of file diff --git a/tests/test_app_config.py b/tests/test_app_config.py new file mode 100644 index 0000000..e30da45 --- /dev/null +++ b/tests/test_app_config.py @@ -0,0 +1,128 @@ +import unittest +import os +from datetime import timedelta + +from flask import current_app +from flask_testing import TestCase + +from config import BaseConfig +from run import application + + +class TestTestingConfig(TestCase): + def create_app(self): + application.config.from_object("config.TestingConfig") + + secret_key = os.getenv("SECRET_KEY", None) + application.config["SECRET_KEY"] = ( + secret_key if secret_key else "TEST_SECRET_KEY" + ) + return application + + def test_app_testing_config(self): + self.assertIsNotNone(application.config["SECRET_KEY"]) + self.assertFalse(application.config["DEBUG"]) + self.assertTrue(application.config["TESTING"]) + self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) + self.assertTrue(application.config["MOCK_EMAIL"]) + self.assertEqual("postgresql:///bit_schema_test", application.config["SQLALCHEMY_DATABASE_URI"] + ) + self.assertIsNotNone(current_app) + + + def test_get_db_uri_function(self): + + expected_result = "db_type_example://db_user_example:db_password_example@db_endpoint_example/db_name_example" + actual_result = BaseConfig.build_db_uri( + db_type_arg="db_type_example", + db_user_arg="db_user_example", + db_password_arg="db_password_example", + db_endpoint_arg="db_endpoint_example", + db_name_arg="db_name_example", + ) + self.assertEqual(expected_result, actual_result) + + +class TestDevelopmentConfig(TestCase): + def create_app(self): + application.config.from_object("config.DevelopmentConfig") + + secret_key = os.getenv("SECRET_KEY", None) + application.config["SECRET_KEY"] = ( + secret_key if secret_key else "TEST_SECRET_KEY" + ) + + return application + + def test_app_development_config(self): + self.assertIsNotNone(application.config["SECRET_KEY"]) + self.assertTrue(application.config["DEBUG"]) + self.assertFalse(application.config["TESTING"]) + self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) + self.assertIsNotNone(current_app) + + + + +class TestStagingConfig(TestCase): + def create_app(self): + application.config.from_object("config.StagingConfig") + + secret_key = os.getenv("SECRET_KEY", None) + application.config["SECRET_KEY"] = ( + secret_key if secret_key else "TEST_SECRET_KEY" + ) + + return application + + def test_app_development_config(self): + self.assertIsNotNone(application.config["SECRET_KEY"]) + self.assertTrue(application.config["DEBUG"]) + self.assertFalse(application.config["TESTING"]) + self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) + self.assertIsNotNone(current_app) + + +class TestLocalConfig(TestCase): + def create_app(self): + application.config.from_object("config.LocalConfig") + + secret_key = os.getenv("SECRET_KEY", None) + application.config["SECRET_KEY"] = ( + secret_key if secret_key else "TEST_SECRET_KEY" + ) + return application + + def test_app_development_config(self): + self.assertIsNotNone(application.config["SECRET_KEY"]) + self.assertTrue(application.config["DEBUG"]) + self.assertFalse(application.config["TESTING"]) + self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) + self.assertEqual( + "postgresql:///bit_schema", application.config["SQLALCHEMY_DATABASE_URI"] + ) + self.assertIsNotNone(current_app) + + +class TestProductionConfig(TestCase): + def create_app(self): + application.config.from_object("config.ProductionConfig") + + secret_key = os.getenv("SECRET_KEY", None) + application.config["SECRET_KEY"] = ( + secret_key if secret_key else "TEST_SECRET_KEY" + ) + + return application + + def test_app_production_config(self): + self.assertIsNotNone(application.config["SECRET_KEY"]) + self.assertFalse(application.config["DEBUG"]) + self.assertFalse(application.config["TESTING"]) + self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) + # self.assertEqual('mysql_something', application.config['SQLALCHEMY_DATABASE_URI']) + self.assertIsNotNone(current_app) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/tests/test_data.py b/tests/test_data.py new file mode 100644 index 0000000..6bffdaa --- /dev/null +++ b/tests/test_data.py @@ -0,0 +1,95 @@ +test_admin_user = { + "name": "Admin", + "email": "admin@email.com", + "username": "admin_username", + "password": "admin_pwd", + "terms_and_conditions_checked": True, +} + +test_admin_user_2 = { + "name": "Admin_2", + "email": "admin2@email.com", + "username": "admin2_username", + "password": "admin2_pwd", + "terms_and_conditions_checked": True, +} + +test_admin_user_3 = { + "name": "Admin_3", + "email": "admin3@email.com", + "username": "admin3_username", + "password": "admin3_pwd", + "terms_and_conditions_checked": True, +} + + +user1 = { + "name": "User", + "email": "user1@email.com", + "username": "user1", + "password": "user1_pwd", + "terms_and_conditions_checked": True, + "available_to_mentor": True, + "need_mentoring": True, +} + +user2 = { + "name": "Userb", + "email": "user2@email.com", + "username": "user2", + "password": "user2_pwd", + "terms_and_conditions_checked": True, +} + +user3 = { + "name": "s_t-r$a/n'ge name", + "email": "user3@email.com", + "username": "user3", + "password": "user3_pwd", + "terms_and_conditions_checked": True, +} + +user4 = { + "name": "user4@email.com", + "email": "user4@email.com", + "username": "user4", + "password": "user4_pwd", + "terms_and_conditions_checked": True, +} + +program1 = { + "program_name": "Program One", + "organizations": { + "rep_id": { + "name": "User", + "email": "user1@email.com", + "username": "user1", + "password": "user1_pwd", + "terms_and_conditions_checked": True, + "available_to_mentor": True, + "need_mentoring": True, + }, + "c_name": "Company ABC", + "c_email": "companyabc@mail.com", + "c_address": "506 Elizabeth St, Melbourne VIC 3000, Australia", + "geoloc": "37.806596, 144.960175", + "c_website": "https://www.ames.net.au" + } +} + +organization1 = { + "rep_id": { + "name": "User", + "email": "user1@email.com", + "username": "user1", + "password": "user1_pwd", + "terms_and_conditions_checked": True, + "available_to_mentor": True, + "need_mentoring": True, + }, + "c_name": "Company ABC", + "c_email": "companyabc@mail.com", + "c_address": "506 Elizabeth St, Melbourne VIC 3000, Australia", + "geoloc": "37.806596, 144.960175", + "c_website": "https://www.ames.net.au" +} \ No newline at end of file diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..cded70b --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,22 @@ +from flask_jwt_extended import create_access_token, create_refresh_token + + +def get_test_request_header(user_identity, token_expiration_delta=None, refresh=False): + """ + This function returns the header needed to access auth protected + endpoints + :param token_expiration_delta: time for the token to expire + :param user_identity: identifier of the user + :param refresh: True if refresh token + :return: header dict with Authorization field + """ + if refresh: + token = create_refresh_token( + identity=user_identity, expires_delta=token_expiration_delta + ) + else: + token = create_access_token( + identity=user_identity, expires_delta=token_expiration_delta + ) + header = {"Authorization": "Bearer {}".format(token)} + return header \ No newline at end of file