diff --git a/CHANGELOG.md b/CHANGELOG.md index a973a12431..b5ad168390 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ## Added - New script to add nypl_login flag to Links objects - Added nypl_login flag to nypl mapping +- New APIUtils method to generate a presigned url for S3 actions ## Fixed - NYPL records not being added due to SQLAlchemy error diff --git a/api/utils.py b/api/utils.py index 5f740e65b1..5af6829fbf 100644 --- a/api/utils.py +++ b/api/utils.py @@ -6,11 +6,16 @@ from model import Collection, Edition import re from model.postgres.collection import COLLECTION_EDITIONS +from logger import createLog +from botocore.exceptions import ClientError + + +logger = createLog(__name__) class APIUtils(): QUERY_TERMS = [ 'keyword', 'title', 'author', 'subject', 'identifier', 'authority: identifier', 'viaf', 'lcnaf', - 'date', 'startYear', 'endYear', 'language', 'format', 'govDoc', 'showAll' + 'date', 'startYear', 'endYear', 'language', 'format', 'govDoc', 'showAll', 'key' ] FORMAT_CROSSWALK = { @@ -508,3 +513,26 @@ def validatePassword(password, hash, salt): hashedPassword = scrypt(password, salt=salt, n=2**14, r=8, p=1) return hashedPassword == hash + + @staticmethod + def generate_presigned_url(s3_client, client_method, method_parameters, expires_in): + """ + Generate a presigned Amazon S3 URL that can be used to perform an action. + + :param s3_client: A Boto3 Amazon S3 client. + :param client_method: The name of the client method that the URL performs. + :param method_parameters: The parameters of the specified client method. + :param expires_in: The number of seconds the presigned URL is valid for. + :return: The presigned URL. + """ + try: + url = s3_client.generate_presigned_url( + ClientMethod=client_method, Params=method_parameters, ExpiresIn=expires_in + ) + logger.info("Got presigned URL: %s", url) + except ClientError: + logger.exception( + "Couldn't get a presigned URL for client method '%s'.", client_method + ) + raise + return url \ No newline at end of file diff --git a/scripts/nyplLoginFlags.py b/scripts/nyplLoginFlags.py index 9911b8fb21..a356d991c8 100644 --- a/scripts/nyplLoginFlags.py +++ b/scripts/nyplLoginFlags.py @@ -23,7 +23,7 @@ def main(): for link in dbManager.session.query(Link) \ .filter(or_(Link.media_type == 'application/html+edd', Link.media_type == 'application/x.html+edd')).all(): - if link.flags['edd'] == True: + if link.flags and 'edd' in link.flags and link.flags['edd'] == True: #The link.flags doesn't update if the dict method isn't called on it newLinkFlag = dict(link.flags) newLinkFlag['nypl_login'] = True diff --git a/tests/unit/test_api_work_blueprint.py b/tests/unit/test_api_work_blueprint.py index bec039bcc8..386f9df317 100644 --- a/tests/unit/test_api_work_blueprint.py +++ b/tests/unit/test_api_work_blueprint.py @@ -5,7 +5,7 @@ from api.utils import APIUtils -class TestSearchBlueprint: +class TestWorkBlueprint: @pytest.fixture def mockUtils(self, mocker): return mocker.patch.multiple(