Skip to content

Commit fe18443

Browse files
Merge pull request #47 from PSNAppz/develop
Added Security Dependency + DB Optimizations
2 parents f05dcc5 + 2fb4c63 commit fe18443

16 files changed

+679
-84
lines changed

.github/workflows/openapi-push.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ jobs:
2323
python-version: "3.10"
2424
- name: Install app
2525
run: |
26-
python -m pip install git+https://github.com/openg2p/openg2p-fastapi-common@develop\#subdirectory=openg2p-fastapi-common
27-
python -m pip install git+https://github.com/openg2p/openg2p-g2pconnect-common-lib@develop\#subdirectory=openg2p-g2pconnect-common-lib
28-
python -m pip install git+https://github.com/openg2p/openg2p-g2pconnect-common-lib@develop\#subdirectory=openg2p-g2pconnect-mapper-lib
26+
python -m pip install git+https://github.com/openg2p/openg2p-fastapi-common@1.0.0\#subdirectory=openg2p-fastapi-common
27+
python -m pip install git+https://github.com/openg2p/openg2p-g2pconnect-common-lib@1.1.0\#subdirectory=openg2p-g2pconnect-common-lib
28+
python -m pip install git+https://github.com/openg2p/openg2p-g2pconnect-common-lib@1.1.0\#subdirectory=openg2p-g2pconnect-mapper-lib
2929
python -m pip install .
3030
- name: Generate openapi json
3131
run: |

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ ADD --chown=${container_user}:${container_user_group} . /app/src
2020
ADD --chown=${container_user}:${container_user_group} main.py /app
2121

2222
RUN python3 -m pip install \
23-
git+https://github.com/openg2p/openg2p-fastapi-common@develop\#subdirectory=openg2p-fastapi-common \
24-
git+https://github.com/OpenG2P/openg2p-g2pconnect-common-lib@develop\#subdirectory=openg2p-g2pconnect-common-lib \
25-
git+https://github.com/OpenG2P/openg2p-g2pconnect-common-lib@develop\#subdirectory=openg2p-g2pconnect-mapper-lib \
23+
git+https://github.com/openg2p/openg2p-fastapi-common@1.0.0\#subdirectory=openg2p-fastapi-common \
24+
git+https://github.com/OpenG2P/openg2p-g2pconnect-common-lib@1.1.0\#subdirectory=openg2p-g2pconnect-common-lib \
25+
git+https://github.com/OpenG2P/openg2p-g2pconnect-common-lib@1.1.0\#subdirectory=openg2p-g2pconnect-mapper-lib \
2626
./src
2727

2828
ENV SPAR_MAPPER_WORKER_TYPE=gunicorn

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ FastAPI based micro service providing Beneficiary ID and Financial Account Mappi
1111
## Licenses
1212

1313
This repository is licensed under [MPL-2.0](LICENSE).
14+

main.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
from openg2p_fastapi_common.ping import PingInitializer
88

9-
main_init = Initializer()
9+
10+
initializer = Initializer()
1011
PingInitializer()
1112

12-
app = main_init.return_app()
13+
app = initializer.return_app()
1314

1415
if __name__ == "__main__":
15-
main_init.main()
16+
initializer.main()

src/openg2p_spar_mapper_api/app.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
_config = Settings.get_config()
77

88
from openg2p_fastapi_common.app import Initializer as BaseInitializer
9+
from openg2p_g2pconnect_common_lib.oauth_token import OAuthTokenService
910

1011
from .controllers import (
1112
AsyncMapperController,
@@ -18,6 +19,7 @@
1819
IdFaMappingValidations,
1920
MapperService,
2021
RequestValidation,
22+
SessionInitializer,
2123
SyncRequestHelper,
2224
SyncResponseHelper,
2325
)
@@ -27,6 +29,8 @@ class Initializer(BaseInitializer):
2729
def initialize(self, **kwargs):
2830
super().initialize()
2931

32+
OAuthTokenService()
33+
SessionInitializer()
3034
MapperService()
3135
IdFaMappingValidations()
3236
SyncRequestHelper()

src/openg2p_spar_mapper_api/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional
22

3-
from openg2p_fastapi_common.config import Settings as BaseSettings
3+
from openg2p_g2pconnect_common_lib.config import Settings as BaseSettings
44
from pydantic import AnyUrl
55
from pydantic_settings import SettingsConfigDict
66

src/openg2p_spar_mapper_api/controllers/async_mapper_controller.py

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import asyncio
22
import logging
33
import uuid
4+
from typing import Annotated
45

56
import httpx
7+
from fastapi import Depends
68
from openg2p_fastapi_common.controller import BaseController
9+
from openg2p_g2pconnect_common_lib.jwt_signature_validator import JWTSignatureValidator
710
from openg2p_g2pconnect_common_lib.schemas import (
811
AsyncCallbackRequest,
912
AsyncResponse,
@@ -89,8 +92,21 @@ def __init__(self, **kwargs):
8992
methods=["POST"],
9093
)
9194

92-
async def link_async(self, link_request: LinkRequest):
95+
async def link_async(
96+
self,
97+
link_request: LinkRequest,
98+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
99+
):
93100
correlation_id = str(uuid.uuid4())
101+
try:
102+
RequestValidation.get_component().validate_signature(is_signature_valid)
103+
except RequestValidationException as e:
104+
error_response = (
105+
AsyncResponseHelper.get_component().construct_error_async_response(
106+
link_request, e
107+
)
108+
)
109+
return error_response
94110
await asyncio.create_task(
95111
self.handle_service_and_link_callback(link_request, correlation_id, "link")
96112
)
@@ -99,8 +115,21 @@ async def link_async(self, link_request: LinkRequest):
99115
correlation_id,
100116
)
101117

102-
async def update_async(self, update_request: UpdateRequest):
118+
async def update_async(
119+
self,
120+
update_request: UpdateRequest,
121+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
122+
):
103123
correlation_id = str(uuid.uuid4())
124+
try:
125+
RequestValidation.get_component().validate_signature(is_signature_valid)
126+
except RequestValidationException as e:
127+
error_response = (
128+
AsyncResponseHelper.get_component().construct_error_async_response(
129+
update_request, e
130+
)
131+
)
132+
return error_response
104133
await asyncio.create_task(
105134
self.handle_service_and_update_callback(
106135
update_request, correlation_id, "update"
@@ -111,8 +140,21 @@ async def update_async(self, update_request: UpdateRequest):
111140
correlation_id,
112141
)
113142

114-
async def resolve_async(self, resolve_request: ResolveRequest):
143+
async def resolve_async(
144+
self,
145+
resolve_request: ResolveRequest,
146+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
147+
):
115148
correlation_id = str(uuid.uuid4())
149+
try:
150+
RequestValidation.get_component().validate_signature(is_signature_valid)
151+
except RequestValidationException as e:
152+
error_response = (
153+
AsyncResponseHelper.get_component().construct_error_async_response(
154+
resolve_request, e
155+
)
156+
)
157+
return error_response
116158
await asyncio.create_task(
117159
self.handle_service_and_resolve_callback(
118160
resolve_request, correlation_id, "resolve"
@@ -123,8 +165,21 @@ async def resolve_async(self, resolve_request: ResolveRequest):
123165
correlation_id,
124166
)
125167

126-
async def unlink_async(self, unlink_request: UnlinkRequest):
168+
async def unlink_async(
169+
self,
170+
unlink_request: UnlinkRequest,
171+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
172+
):
127173
correlation_id = str(uuid.uuid4())
174+
try:
175+
RequestValidation.get_component().validate_signature(is_signature_valid)
176+
except RequestValidationException as e:
177+
error_response = (
178+
AsyncResponseHelper.get_component().construct_error_async_response(
179+
unlink_request, e
180+
)
181+
)
182+
return error_response
128183
try:
129184
RequestValidation.get_component().validate_request(unlink_request)
130185
RequestValidation.get_component().validate_unlink_async_request_header(
@@ -148,7 +203,10 @@ async def unlink_async(self, unlink_request: UnlinkRequest):
148203
)
149204

150205
async def handle_service_and_link_callback(
151-
self, link_request: LinkRequest, correlation_id: str, action: str
206+
self,
207+
link_request: LinkRequest,
208+
correlation_id: str,
209+
action: str,
152210
):
153211
try:
154212
RequestValidation.get_component().validate_async_request(link_request)

src/openg2p_spar_mapper_api/controllers/sync_mapper_controller.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
from typing import Annotated
2+
3+
from fastapi import Depends
14
from openg2p_fastapi_common.controller import BaseController
5+
from openg2p_g2pconnect_common_lib.jwt_signature_validator import JWTSignatureValidator
26
from openg2p_g2pconnect_mapper_lib.schemas import (
37
LinkRequest,
48
LinkResponse,
@@ -55,8 +59,13 @@ def __init__(self, **kwargs):
5559
methods=["POST"],
5660
)
5761

58-
async def link_sync(self, link_request: LinkRequest):
62+
async def link_sync(
63+
self,
64+
link_request: LinkRequest,
65+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
66+
):
5967
try:
68+
RequestValidation.get_component().validate_signature(is_signature_valid)
6069
RequestValidation.get_component().validate_request(link_request)
6170
RequestValidation.get_component().validate_link_request_header(link_request)
6271
except RequestValidationException as e:
@@ -75,8 +84,13 @@ async def link_sync(self, link_request: LinkRequest):
7584
single_link_responses,
7685
)
7786

78-
async def update_sync(self, update_request: UpdateRequest):
87+
async def update_sync(
88+
self,
89+
update_request: UpdateRequest,
90+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
91+
):
7992
try:
93+
RequestValidation.get_component().validate_signature(is_signature_valid)
8094
RequestValidation.get_component().validate_request(update_request)
8195
RequestValidation.get_component().validate_update_request_header(
8296
update_request
@@ -99,8 +113,13 @@ async def update_sync(self, update_request: UpdateRequest):
99113
)
100114
)
101115

102-
async def resolve_sync(self, resolve_request: ResolveRequest):
116+
async def resolve_sync(
117+
self,
118+
resolve_request: ResolveRequest,
119+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
120+
):
103121
try:
122+
RequestValidation.get_component().validate_signature(is_signature_valid)
104123
RequestValidation.get_component().validate_request(resolve_request)
105124
RequestValidation.get_component().validate_resolve_request_header(
106125
resolve_request
@@ -123,8 +142,13 @@ async def resolve_sync(self, resolve_request: ResolveRequest):
123142
)
124143
)
125144

126-
async def unlink_sync(self, unlink_request: UnlinkRequest):
145+
async def unlink_sync(
146+
self,
147+
unlink_request: UnlinkRequest,
148+
is_signature_valid: Annotated[bool, Depends(JWTSignatureValidator())],
149+
):
127150
try:
151+
RequestValidation.get_component().validate_signature(is_signature_valid)
128152
RequestValidation.get_component().validate_request(unlink_request)
129153
RequestValidation.get_component().validate_unlink_request_header(
130154
unlink_request

src/openg2p_spar_mapper_api/services/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
from .request_helper import AsyncRequestHelper, SyncRequestHelper
55
from .request_validations import RequestValidation
66
from .response_helper import AsyncResponseHelper, SyncResponseHelper
7+
from .session_service import SessionInitializer

src/openg2p_spar_mapper_api/services/id_fa_mapping_validations.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,28 +94,14 @@ async def validate_update_request(
9494
return None
9595

9696
async def validate_resolve_request(
97-
self, connection, single_resolve_request: SingleResolveRequest
97+
self, single_resolve_request: SingleResolveRequest
9898
) -> None:
9999
if not single_resolve_request.id and not single_resolve_request.fa:
100100
raise ResolveValidationException(
101101
message="ID is required",
102102
status=StatusEnum.rjct,
103103
validation_error_type=ResolveStatusReasonCode.rjct_reference_id_invalid,
104104
)
105-
106-
result = await connection.execute(
107-
select(IdFaMapping).where(
108-
IdFaMapping.id_value == single_resolve_request.id,
109-
)
110-
)
111-
resolve_request_from_db = result.first()
112-
113-
if not resolve_request_from_db:
114-
raise ResolveValidationException(
115-
message="ID doesnt exist please link first",
116-
status=StatusEnum.succ,
117-
validation_error_type=ResolveStatusReasonCode.succ_fa_not_linked_to_id,
118-
)
119105
return None
120106

121107
async def validate_unlink_request(

0 commit comments

Comments
 (0)