diff --git a/app/blueprints/user_blueprint.py b/app/blueprints/user_blueprint.py index 2968123..422dd6e 100755 --- a/app/blueprints/user_blueprint.py +++ b/app/blueprints/user_blueprint.py @@ -111,6 +111,34 @@ def update_user(user_id): return user_controller.update_user(user_id) +@user_blueprint.route("//info", methods=["PUT", "PATCH"]) +# @cross_origin(supports_credentials=True) +@Auth.has_permission(["update_user", "update_user_self"]) +@Security.validator( + [ + "first_name|required", + "last_name|required", + "job_title|optional", + "experience_years|optional", + "phone|optional", + "user_id|required", + "git_hub|optional", + "linked_in|optional", + "personal_email|optional:url", + ] +) +# @swag_from('documentation/update_user.yml') +def update_user_info(user_id): + return user_controller.update_user_info(user_id) + + +@user_blueprint.route("//image", methods=["PUT", "PATCH"]) +# @cross_origin(supports_credentials=True) +@Auth.has_permission(["update_user", "update_user_self"]) +def update_profile_image(user_id): + return user_controller.update_profile_image(user_id) + + @user_blueprint.route("/login", methods=["POST"]) def authenticate_user(): return user_controller.authenticate_user() diff --git a/app/controllers/user_controller.py b/app/controllers/user_controller.py index e70de9f..c6efd47 100755 --- a/app/controllers/user_controller.py +++ b/app/controllers/user_controller.py @@ -7,6 +7,8 @@ from werkzeug.security import check_password_hash, generate_password_hash from app.utils.id_generator import PushID +ALLOWED_EXTENSIONS = set(["jpg", "jpeg", "png"]) + class UserController(BaseController): """ @@ -87,8 +89,15 @@ def list_all_users(self): per_page = params.get("per_page") users = self.user_repo.paginate(error_out=False, page=page, per_page=per_page) + user_list = [] if users.items: - user_list = [user.serialize() for user in users.items] + for user in users.items: + user_item = user.serialize() + if user.employment_date is not None: + user_item["employment_date"] = user.employment_date.strftime( + "%b %d, %Y" + ) + user_list.append(user_item) for user in user_list: associated_roles = [ user_role.role_id @@ -375,6 +384,42 @@ def update_user(self, user_id): return self.handle_response("OK", payload={"user": user_data}, status_code=200) + def update_user_info(self, user_id): + user = self.user_repo.find_first_(id=user_id) + + if not user: + return self.handle_response( + msg="FAIL", payload={"user": "User not found"}, status_code=404 + ) + + if user.is_deleted: + return self.handle_response( + msg="FAIL", payload={"user": "User already deleted"}, status_code=400 + ) + + user_info = self.request_params_dict( + "first_name", + "last_name", + "job_title", + "experience_years", + "phone", + "personal_email", + "git_hub", + "linked_in", + ) + import pdb + + pdb.set_trace() + user = self.user_repo.update(user, **user_info) + user_data = user.serialize() + del user_data["password"] + user_roles = self.user_role_repo.get_unpaginated(user_id=user_id) + user_data["user_roles"] = [ + user_role.role.to_dict(only=["id", "name"]) for user_role in user_roles + ] + + return self.handle_response("OK", payload={"user": user_data}, status_code=200) + def authenticate_user(self): username, password = self.request_params("username", "password") user = self.user_repo.find_first(email=username) diff --git a/app/models/client.py b/app/models/client.py index 3cae615..4b11345 100644 --- a/app/models/client.py +++ b/app/models/client.py @@ -3,3 +3,11 @@ class Client(BaseModel): __tablename__ = "clients" + + institution_name = db.Column(db.String, nullable=False) + institution_url = db.Column(db.String, nullable=True) + institution_city = db.Column(db.String, nullable=False) + institution_country = db.Column(db.String, nullable=False) + institution_size = db.Column(db.String, nullable=True) + job_title_needed = db.Column(db.String, nullable=True) + job_description = db.Column(db.Text, nullable=True) diff --git a/app/models/user_client.py b/app/models/user_client.py index 5056a14..b8f4429 100644 --- a/app/models/user_client.py +++ b/app/models/user_client.py @@ -1,5 +1,21 @@ from .base_model import BaseModel, db +from ..utils.enums import EmploymentType class UserClient(BaseModel): __tablename__ = "user_clients" + + institution_name = db.Column(db.String, nullable=False) + job_title = db.Column(db.String, nullable=False) + employment_type = db.Column( + db.Enum(EmploymentType, values_callable=lambda obj: [e.value for e in obj]), + nullable=True, + ) + institution_url = db.Column(db.String, nullable=True) + institution_city = db.Column(db.String, nullable=False) + institution_country = db.Column(db.String, nullable=False) + institution_size = db.Column(db.String, nullable=True) + user_id = db.Column(db.Integer(), db.ForeignKey("users.id")) + user = db.relationship("User", lazy=False) + client_id = db.Column(db.Integer(), db.ForeignKey("clients.id")) + client = db.relationship("Client", lazy=False) diff --git a/factories/client_factory.py b/factories/client_factory.py new file mode 100644 index 0000000..a6a4678 --- /dev/null +++ b/factories/client_factory.py @@ -0,0 +1,18 @@ +import factory +from app.utils import db +from app.models.client import Client + +# Any Table fields that cannot be generated by factory.Faker() should be defined out here and used inside the class. +# This is a limitation on how factory-boy serializes args created in the Factory class. +# example +# fake_cohort_position = 'Vice President' + + +class ClientFactory(factory.alchemy.SQLAlchemyModelFactory): + class Meta: + model = Client + sqlalchemy_session = db.session + + id = factory.Sequence(lambda n: n) + # name = factory.Faker('name') + # cohort_position = fake_cohort_position diff --git a/factories/user_client_factory.py b/factories/user_client_factory.py new file mode 100644 index 0000000..81df18c --- /dev/null +++ b/factories/user_client_factory.py @@ -0,0 +1,18 @@ +import factory +from app.utils import db +from app.models.user_client import UserClient + +# Any Table fields that cannot be generated by factory.Faker() should be defined out here and used inside the class. +# This is a limitation on how factory-boy serializes args created in the Factory class. +# example +# fake_cohort_position = 'Vice President' + + +class UserClientFactory(factory.alchemy.SQLAlchemyModelFactory): + class Meta: + model = UserClient + sqlalchemy_session = db.session + + id = factory.Sequence(lambda n: n) + # name = factory.Faker('name') + # cohort_position = fake_cohort_position