Skip to content

Commit

Permalink
Merge pull request #33 from jadmsaadaot/SUBMIT-task#16
Browse files Browse the repository at this point in the history
Load and confirm project data - integrate front-end and backend
  • Loading branch information
djnunez-aot authored Aug 16, 2024
2 parents f367ff7 + 0e87bcd commit dea5346
Show file tree
Hide file tree
Showing 47 changed files with 404 additions and 95 deletions.
2 changes: 1 addition & 1 deletion submit-api/migrations/versions/0223afc14044_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Create Date: 2024-07-26 13:15:57.023621
"""
from alembic import op
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
Expand Down
2 changes: 1 addition & 1 deletion submit-api/migrations/versions/20bcb68bc2ac_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Create Date: 2024-06-27 14:22:33.838724
"""
from alembic import op
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
Expand Down
32 changes: 32 additions & 0 deletions submit-api/migrations/versions/5a6eda61c0c4_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Add name to account projects
Revision ID: 5a6eda61c0c4
Revises: aeb2ae9d64b9
Create Date: 2024-08-15 11:55:47.490418
"""
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
revision = '5a6eda61c0c4'
down_revision = 'aeb2ae9d64b9'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('account_projects', schema=None) as batch_op:
batch_op.add_column(sa.Column('name', sa.String(), nullable=False))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('account_projects', schema=None) as batch_op:
batch_op.drop_column('name')

# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion submit-api/migrations/versions/6dfc3501adbb_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Create Date: 2024-07-30 10:48:21.496460
"""
from alembic import op
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
Expand Down
2 changes: 1 addition & 1 deletion submit-api/migrations/versions/8e112bda0a34_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Create Date: 2024-07-30 13:52:28.545333
"""
from alembic import op
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
Expand Down
2 changes: 1 addition & 1 deletion submit-api/migrations/versions/97de805275ec_.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"""
from datetime import datetime

from alembic import op
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
Expand Down
3 changes: 2 additions & 1 deletion submit-api/migrations/versions/aeb2ae9d64b9_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
Create Date: 2024-08-12 10:18:32.687612
"""
from alembic import op
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql


# revision identifiers, used by Alembic.
revision = 'aeb2ae9d64b9'
down_revision = '8e112bda0a34'
Expand Down
1 change: 1 addition & 0 deletions submit-api/src/submit_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from submit_api.utils.cache import cache
from submit_api.utils.util import allowedorigins


# Security Response headers
csp = (
secure.ContentSecurityPolicy()
Expand Down
1 change: 1 addition & 0 deletions submit-api/src/submit_api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from flask import g, request
from flask_jwt_oidc import JwtManager


jwt = (
JwtManager()
) # pylint: disable=invalid-name; lower case name as used by convention in most Flask apps
Expand Down
1 change: 1 addition & 0 deletions submit-api/src/submit_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from dotenv import find_dotenv, load_dotenv


# this will load all the envars from a .env file located in the project root (api)
load_dotenv(find_dotenv())

Expand Down
2 changes: 1 addition & 1 deletion submit-api/src/submit_api/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
error - a description of the error {code / description: classname / full text}
status_code - where possible use HTTP Error Codes
"""
from werkzeug.exceptions import UnprocessableEntity, Forbidden, NotFound, BadRequest, Conflict
from werkzeug.exceptions import BadRequest, Conflict, Forbidden, NotFound, UnprocessableEntity
from werkzeug.wrappers.response import Response


Expand Down
8 changes: 4 additions & 4 deletions submit-api/src/submit_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

"""This exports all of the models and schemas used by the application."""

from .db import db, ma, migrate
from .account import Account
from .account_project import AccountProject
from .account_role import AccountRole
from .account_user import AccountUser
from .role import Role
from .account import Account
from .base_model import BaseModel
from .account_project import AccountProject
from .db import db, ma, migrate
from .project_team import ProjectTeam
from .role import Role
8 changes: 8 additions & 0 deletions submit-api/src/submit_api/models/account_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ class AccountProject(BaseModel):
id = Column(db.Integer, primary_key=True, autoincrement=True)
account_id = Column(db.Integer, ForeignKey('accounts.id'), nullable=False)
project_id = Column(db.Integer, nullable=False)
name = Column(db.String(), nullable=False)

@classmethod
def add_projects_bulk(cls, projects):
"""Add projects in bulk."""
db.session.bulk_insert_mappings(cls, projects)
db.session.commit()
return projects
8 changes: 6 additions & 2 deletions submit-api/src/submit_api/models/account_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from __future__ import annotations

from sqlalchemy import Column, ForeignKey
from sqlalchemy import Column, ForeignKey, Index
from sqlalchemy.orm import column_property

from .base_model import BaseModel
Expand All @@ -24,7 +24,11 @@ class AccountUser(BaseModel):
position = Column(db.String(100), nullable=False)
work_email_address = Column(db.String(100), nullable=False)
work_contact_number = Column(db.String(50), nullable=False)
auth_guid = Column(db.String(), nullable=False)
auth_guid = Column(db.String(), nullable=False, unique=True)

__table_args__ = (
Index('ix_account_users_auth_guid', 'auth_guid', unique=True),
)

@classmethod
def create_account_user(cls, data, session=None) -> AccountUser:
Expand Down
1 change: 1 addition & 0 deletions submit-api/src/submit_api/models/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from .db import db


TENANT_ID = 'tenant_id'


Expand Down
2 changes: 2 additions & 0 deletions submit-api/src/submit_api/models/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy


# DB initialize in __init__ file
# db variable use for create models from here
db = SQLAlchemy()
Expand Down
7 changes: 4 additions & 3 deletions submit-api/src/submit_api/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@

from flask import Blueprint


from .account import API as ACCOUNT_API
from .apihelper import Api

from .ops import API as OPS_API
from .account import API as ACCOUNT_API
from .project import API as PROJECT_API
from .user import API as USER_API


__all__ = ('API_BLUEPRINT', 'OPS_BLUEPRINT')

URL_PREFIX = '/api/'
Expand All @@ -56,3 +56,4 @@

API.add_namespace(ACCOUNT_API)
API.add_namespace(USER_API)
API.add_namespace(PROJECT_API)
7 changes: 5 additions & 2 deletions submit-api/src/submit_api/resources/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
from http import HTTPStatus

from flask_restx import Namespace, Resource, cors

from submit_api.exceptions import ResourceNotFoundError
from submit_api.schemas.account import AccountCreateSchema, AccountSchema
from submit_api.services.account_service import AccountService
from submit_api.utils.util import cors_preflight
from submit_api.schemas.account import AccountSchema, AccountCreateSchema
from submit_api.exceptions import ResourceNotFoundError

from .apihelper import Api as ApiHelper


API = Namespace("accounts", description="Endpoints for Account Management")
"""Custom exception messages
"""
Expand Down
4 changes: 3 additions & 1 deletion submit-api/src/submit_api/resources/apihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
to support swagger on http
"""
from functools import wraps

from flask import url_for
from flask_restx import Api as BaseApi, fields
from flask_restx import Api as BaseApi
from flask_restx import fields
from flask_restx.apidoc import apidoc
from marshmallow import fields as ma_fields

Expand Down
54 changes: 54 additions & 0 deletions submit-api/src/submit_api/resources/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright © 2024 Province of British Columbia
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""API endpoints for managing a project resource."""

from http import HTTPStatus

from flask_restx import Namespace, Resource, cors

from submit_api.schemas.project import AddProjectSchema, ProjectSchema
from submit_api.services.project_service import ProjectService
from submit_api.utils.util import cors_preflight

from .apihelper import Api as ApiHelper


API = Namespace("projects", description="Endpoints for Project Management")
"""Custom exception messages
"""

project_add_list = ApiHelper.convert_ma_schema_to_restx_model(
API, AddProjectSchema(), "Project Add"
)
project_list_model = ApiHelper.convert_ma_schema_to_restx_model(
API, ProjectSchema(), "Project"
)


@cors_preflight("GET, OPTIONS, POST")
@API.route("", methods=["POST", "GET", "OPTIONS"])
class Projects(Resource):
"""Resource for managing projects."""

@staticmethod
@ApiHelper.swagger_decorators(API, endpoint_description="Add projects in bulk")
@API.expect(project_add_list)
@API.response(code=HTTPStatus.CREATED, model=project_list_model, description="Added projects")
@API.response(HTTPStatus.BAD_REQUEST, "Bad Request")
@cors.crossdomain(origin="*")
def post():
"""Add projects in bulk."""
projects_data = AddProjectSchema(many=True).load(API.payload)
added_projects = ProjectService.bulk_add_projects(projects_data)
return ProjectSchema(many=True).dump(added_projects), HTTPStatus.CREATED
7 changes: 5 additions & 2 deletions submit-api/src/submit_api/resources/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
from http import HTTPStatus

from flask_restx import Namespace, Resource, cors
from submit_api.utils.util import cors_preflight

from submit_api.exceptions import ResourceNotFoundError
from .apihelper import Api as ApiHelper
from submit_api.utils.util import cors_preflight

from ..schemas.user import UserSchema
from ..services.user_service import UserService
from .apihelper import Api as ApiHelper


API = Namespace("users", description="Endpoints for Account Management")
"""Custom exception messages
Expand Down
14 changes: 14 additions & 0 deletions submit-api/src/submit_api/schemas/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,19 @@ class Meta: # pylint: disable=too-few-public-methods
unknown = EXCLUDE

id = fields.Int(data_key="id")
name = fields.Str(data_key="name")
project_id = fields.Str(data_key="project_id")
account_id = fields.Str(data_key="account_id")


class AddProjectSchema(Schema):
"""Account schema."""

class Meta: # pylint: disable=too-few-public-methods
"""Exclude unknown fields in the deserialized output."""

unknown = EXCLUDE

name = fields.Str(data_key="name")
project_id = fields.Int(data_key="project_id")
account_id = fields.Int(data_key="account_id")
4 changes: 3 additions & 1 deletion submit-api/src/submit_api/services/account_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Service for account management."""
from submit_api.models import AccountRole as AccountRoleModel, AccountUser as AccountUserModel, Role as RoleModel
from submit_api.models import AccountRole as AccountRoleModel
from submit_api.models import AccountUser as AccountUserModel
from submit_api.models import Role as RoleModel
from submit_api.models.account import Account as AccountModel
from submit_api.models.db import session_scope
from submit_api.models.role import RoleEnum
Expand Down
18 changes: 18 additions & 0 deletions submit-api/src/submit_api/services/project_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Service for project management."""
from submit_api.models.account_project import AccountProject as ProjectModel


class ProjectService:
"""Project management service."""

@classmethod
def get_project_by_id(cls, _project_id):
"""Get project by id."""
db_project = ProjectModel.find_by_id(_project_id)
return db_project

@classmethod
def bulk_add_projects(cls, projects):
"""Add projects in bulk."""
ProjectModel.add_projects_bulk(projects)
return projects
4 changes: 2 additions & 2 deletions submit-api/src/submit_api/utils/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Datetime object helper."""
from datetime import datetime

import pytz
from flask import current_app

from datetime import datetime


def local_datetime():
"""Get the local (Pacific Timezone) datetime."""
Expand Down
1 change: 1 addition & 0 deletions submit-api/tests/unit/resources/test_apihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
to test api helper functions
"""
import pytest

from submit_api.resources.apihelper import Api


Expand Down
1 change: 1 addition & 0 deletions submit-api/tests/utilities/factory_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

from submit_api.config import get_named_config


CONFIG = get_named_config('testing')
fake = Faker()

Expand Down
Loading

0 comments on commit dea5346

Please sign in to comment.