Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue 2512] S3 Presign URL #2563

Merged
merged 40 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4d9dcff
test files
babebe Oct 24, 2024
7728a06
update factory and seed local db
babebe Oct 24, 2024
3b29af1
update opp with presigned url and return
babebe Oct 24, 2024
c5bee75
clean up
babebe Oct 24, 2024
e0dda32
Merge branch 'main' into S3-presign-URL
babebe Oct 24, 2024
66cc915
clean
babebe Oct 24, 2024
387655b
cleanup
babebe Oct 24, 2024
071ffee
merge conlfict
babebe Oct 24, 2024
7da3f4c
add test
babebe Oct 25, 2024
d7510b8
cleanup
babebe Oct 25, 2024
c8ee7ef
unit test
babebe Oct 28, 2024
c454096
cleanup
babebe Oct 28, 2024
c6e62bc
Merge branch 'main' into 2512-s3-presign-url
babebe Oct 28, 2024
88487ae
add timeout to request
babebe Oct 28, 2024
a866aa6
update attachment test
babebe Oct 28, 2024
698687e
fomrat
babebe Oct 28, 2024
bc7b605
update test fixture set new local env
babebe Oct 28, 2024
2cc0466
updatew unit test
babebe Oct 29, 2024
39f048d
Create ERD diagram and Update OpenAPI spec
nava-platform-bot Oct 29, 2024
292f886
clean
babebe Oct 29, 2024
cc6bcac
update response schema and test
babebe Oct 29, 2024
49c7655
Merge remote-tracking branch 'origin/2512-s3-presign-url' into 2512-s…
babebe Oct 29, 2024
451ed0a
Merge branch 'main' into 2512-s3-presign-url
babebe Oct 29, 2024
bf19076
Create ERD diagram and Update OpenAPI spec
nava-platform-bot Oct 29, 2024
1838315
clean up
babebe Oct 29, 2024
f52ebc7
Merge remote-tracking branch 'origin/2512-s3-presign-url' into 2512-s…
babebe Oct 29, 2024
1201d6a
Create ERD diagram and Update OpenAPI spec
nava-platform-bot Oct 29, 2024
6c6a740
update test
babebe Oct 29, 2024
a443fa6
timeout
babebe Oct 29, 2024
1974217
Merge branch 'main' into 2512-s3-presign-url
babebe Oct 29, 2024
6317a45
rm file_location from test
babebe Oct 29, 2024
f56413c
set to localhost when local
babebe Oct 29, 2024
5da0c66
Merge branch 'main' into 2512-s3-presign-url
babebe Oct 29, 2024
2cf28ae
format
babebe Oct 29, 2024
147ea61
clean
babebe Oct 30, 2024
3bd6e18
update get_opportunity
babebe Oct 30, 2024
071134e
format lint
babebe Oct 30, 2024
8a6a622
reusable func and cleanup
babebe Oct 30, 2024
8947231
Create ERD diagram and Update OpenAPI spec
nava-platform-bot Oct 30, 2024
3dd9563
Merge branch 'main' into 2512-s3-presign-url
babebe Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion api/src/services/opportunities_v1/get_opportunity.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import copy
from datetime import date

import boto3
from sqlalchemy import select
from sqlalchemy.orm import noload, selectinload

import src.adapters.db as db
import src.util.datetime_util as datetime_util
from src.adapters.aws import S3Config, get_s3_client
from src.api.route_utils import raise_flask_error
from src.db.models.opportunity_models import Opportunity, OpportunitySummary

Expand All @@ -31,7 +34,30 @@ def _fetch_opportunity(


def get_opportunity(db_session: db.Session, opportunity_id: int) -> Opportunity:
return _fetch_opportunity(db_session, opportunity_id, load_all_opportunity_summaries=False)
opportunity = _fetch_opportunity(
db_session, opportunity_id, load_all_opportunity_summaries=False
)
opportunity_copy = copy.deepcopy(opportunity)

s3_config = S3Config()
s3_config.s3_endpoint_url = "http://localstack:4566"
s3_client = get_s3_client(
s3_config, boto3.Session(aws_access_key_id="NO_CREDS", aws_secret_access_key="NO_CREDS")
)

for opp_attachment in opportunity_copy.opportunity_attachments:
file_loc = opp_attachment.file_location
object_key = file_loc.split(f"{s3_config.s3_opportunity_bucket}/")[
1
] # should be same as filename in db ?
pre_sign_file_loc = s3_client.generate_presigned_url(
"get_object",
Params={"Bucket": s3_config.s3_opportunity_bucket, "Key": object_key},
ExpiresIn=1800,
) # do we want to put limit
opp_attachment.file_location = pre_sign_file_loc

return opportunity_copy


def get_opportunity_versions(db_session: db.Session, opportunity_id: int) -> dict:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, world
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, world
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, world
Binary file not shown.
Binary file not shown.
30 changes: 30 additions & 0 deletions api/tests/lib/seed_local_db.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import logging
import os
import pathlib
import random

import boto3
import click
from botocore.exceptions import ClientError
from sqlalchemy import func

import src.adapters.db as db
import src.logging
import src.util.datetime_util as datetime_util
import tests.src.db.models.factories as factories
from src.adapters.aws import S3Config, get_s3_client
from src.adapters.db import PostgresDBClient
from src.db.models.agency_models import Agency
from src.db.models.opportunity_models import Opportunity
Expand All @@ -16,6 +21,29 @@

logger = logging.getLogger(__name__)

TESTS_FOLDER = pathlib.Path(__file__).parent.resolve()


def upload_opportunity_attachments_s3():
s3_config = S3Config()
s3_client = get_s3_client(
s3_config, boto3.Session(aws_access_key_id="NO_CREDS", aws_secret_access_key="NO_CREDS")
)
test_folder_path = TESTS_FOLDER / "opportunity_attachment_test_files"

for root, _, files in os.walk(test_folder_path):
for file in files:
file_path = os.path.join(root, file)
object_name = os.path.relpath(file_path, test_folder_path)

try:
s3_client.upload_file(file_path, s3_config.s3_opportunity_bucket, object_name)
print(
f"Successfully uploaded {file_path} to s3://{s3_config.s3_opportunity_bucket}/{object_name}"
) # log?
except ClientError as e:
print(f"Error uploading {file_path}: {e}")


def _add_history(
opps: list[Opportunity],
Expand Down Expand Up @@ -173,6 +201,8 @@ def seed_local_db(iterations: int, include_history: bool) -> None:
logger.info("Running seed script for local DB")
error_if_not_local()

upload_opportunity_attachments_s3()

db_client = PostgresDBClient()

with db_client.get_session() as db_session:
Expand Down
13 changes: 12 additions & 1 deletion api/tests/src/db/models/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ class CustomProvider(BaseProvider):

YN_YESNO_BOOLEAN_VALUES = ["Y", "N", "Yes", "No"]

OPPORTUNITY_ATTACHMENT_S3_PATHS = [
"s3://local-opportunities/test_file_1.txt",
"s3://local-opportunities/test_file_2.txt",
"s3://local-opportunities/test_file_3.txt",
"s3://local-opportunities/test_file_4.pdf",
"s3://local-opportunities/test_file_5.pdf",
]

def agency(self) -> str:
return self.random_element(self.AGENCIES)

Expand Down Expand Up @@ -188,6 +196,9 @@ def yn_boolean(self) -> str:
def yn_yesno_boolean(self) -> str:
return self.random_element(self.YN_YESNO_BOOLEAN_VALUES)

def opportunity_attachment(self) -> str:
return self.random_element(self.OPPORTUNITY_ATTACHMENT_S3_PATHS)


fake = faker.Faker()
fake.add_provider(CustomProvider)
Expand Down Expand Up @@ -239,7 +250,7 @@ class OpportunityAttachmentFactory(BaseFactory):
class Meta:
model = opportunity_models.OpportunityAttachment

file_location = factory.Faker("url")
file_location = factory.Faker("opportunity_attachment")
mime_type = factory.Faker("mime_type")
file_name = factory.Faker("file_name")
file_description = factory.Faker("sentence")
Expand Down
Loading