From 688ab1ec6b3e9df9618452dd24d65b66c6b46894 Mon Sep 17 00:00:00 2001 From: Nathaniel Hajel Date: Thu, 13 Feb 2025 20:53:00 -0500 Subject: [PATCH 1/3] More work on SAM with Amplify --- samconfig.toml | 5 ++++- template.yaml | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/samconfig.toml b/samconfig.toml index 2b39600..83d4705 100644 --- a/samconfig.toml +++ b/samconfig.toml @@ -5,9 +5,12 @@ version = 0.1 [default.deploy.parameters] stack_name = "sam-app-dev" region = "us-east-1" -confirm_changeset = false +confirm_changeset = true capabilities = "CAPABILITY_IAM" disable_rollback = true # Example: Allow more tolerance in dev for errors +resolve_s3 = true +s3_prefix = "sam-app-dev" +image_repositories = [] [prod] [prod.deploy] diff --git a/template.yaml b/template.yaml index dba06fc..c120973 100644 --- a/template.yaml +++ b/template.yaml @@ -1,6 +1,42 @@ Transform: AWS::Serverless-2016-10-31 # Need for all SAM templates, Source: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html Resources: + AmplifyApp: + Type: AWS::Amplify::App + Properties: + Name: amplify-sam-demo-app + Repository: https://github.com/mirrulations/mirrulations-website.git + AccessToken: '{{resolve:secretsmanager:github-token}}' + IAMServiceRole: !GetAtt AmplifyRole.Arn + # EnvironmentVariables: + # Name: ENDPOINT + # Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/" + AmplifyRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - amplify.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: Amplify + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: "amplify:*" + Resource: "*" + AmplifyBranch: + Type: AWS::Amplify::Branch + Properties: + BranchName: main + AppId: !GetAtt AmplifyApp.AppId + EnableAutoBuild: true ApiGatewayApi: Type: AWS::Serverless::Api Properties: @@ -18,4 +54,5 @@ Resources: Ref: ApiGatewayApi CodeUri: endpoints/ Handler: app.test_handler # this and the one above are a path to a handler - Runtime: python3.13 \ No newline at end of file + Runtime: python3.13 + \ No newline at end of file From 42182d8dfe442fd86c1955bbf3679dc63570b3ef Mon Sep 17 00:00:00 2001 From: Nathaniel Hajel Date: Fri, 14 Feb 2025 14:53:03 -0500 Subject: [PATCH 2/3] Added the documentation to the readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index b329846..22bca06 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # API +**Authors:** Seth Coleman, Davin Glynn, Trevor Gray, Nathan Hajel, Terrell Nelson, Giovanny Teran, and Brandon Yang +This is the API repo for the Mirrulations Project that contains all the files for SAM and the unit tests. ## How to run the API for testing ### Installing AWS and SAM @@ -39,3 +41,17 @@ The `samconfig.toml` file stores configuration parameters for SAM CLI deployment This README has been adapted to utilize the automated deployment features of AWS SAM, making it easier and faster to manage your deployments. For more detailed information, refer to this [AWS Tutorial](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html#serverless-getting-started-hello-world-delete). + +### How To create a Github actions workflow: + +- It is important to note now and for the future that when making changes to github actions you must **push directly to upstream**. This is typically bad practice but is required for github actions to work. Need more information? Check out the [Discord](https://discord.com/channels/1332506599020822620/1333536321515290646/1336078961943380030). +- Create a directory ./github/workflows in the main repository. +- Create a .yml file which will contain the actions you want to complete. Check out the template [here](https://github.com/mirrulations/CIWebTest/blob/main/.github/workflows/github-actions-demo.yml). + - These commands are run from an ubuntu terminal by a “runner” created by github for this purpose +- Create a github secret to store AWS credentials, this is accomplished in the following steps + - Click _**Settings**_ + - Under _**Secrets and Variables**_ click _**Actions**_ + - Click _**New repository secret**_ and add the secret name and data + - Remember to create a secret for both the access key and the secret access key + +After all this is done your github actions file is complete, you can test it by pushing some minor change or with this [repo](https://github.com/nektos/act) found by our teammate Owen. From 08107d0777bc3e953250893535af0168f0d8745d Mon Sep 17 00:00:00 2001 From: Nathaniel Hajel Date: Thu, 24 Apr 2025 22:06:28 -0400 Subject: [PATCH 3/3] Hopefully fixes prod --- endpoints/app.py | 82 ++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/endpoints/app.py b/endpoints/app.py index 6cbe87f..beb9a81 100644 --- a/endpoints/app.py +++ b/endpoints/app.py @@ -2,74 +2,68 @@ import json def lambda_handler(event, context): - """Sample pure Lambda function - - Parameters - ---------- - event: dict, required - API Gateway Lambda Proxy Input Format - - Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format - - context: object, required - Lambda Context runtime methods and attributes - - Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html - - Returns - ------ - API Gateway Lambda Proxy Output Format: dict - - Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html - """ PARAMETER_NAME = "searchTerm" - # These headers are always included to fix the CORS Issues + # Initialize default response object response = { - 'headers': { - 'Access-Control-Allow-Headers': '*', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': '*' + "statusCode": 200, + "headers": { + "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Accept,Origin,session-id", + "Access-Control-Allow-Methods": "GET,OPTIONS", + "Access-Control-Allow-Origin": "*" # This will be updated dynamically }, + "body": "" } - if 'queryStringParameters' not in event or event['queryStringParameters'] == None or PARAMETER_NAME not in event['queryStringParameters']: + # Determine the origin for CORS + origin = event['headers'].get("origin", "*") + if origin in ["https://mirrulations.com", "https://mirrulations.org"]: + allow_origin = origin + else: + allow_origin = "https://mirrulations.com" + response["headers"]["Access-Control-Allow-Origin"] = allow_origin + + # Handle CORS preflight request + if event['httpMethod'] == 'OPTIONS': + return response + + # Validate query parameters + if 'queryStringParameters' not in event or event['queryStringParameters'] is None or PARAMETER_NAME not in event['queryStringParameters']: response["statusCode"] = 400 - response['body'] = {"error": f"Bad request: Missing query parameter '{PARAMETER_NAME}'"} + response["body"] = json.dumps({"error": f"Bad request: Missing query parameter '{PARAMETER_NAME}'"}) return response - if event['headers'] == None: + if event['headers'] is None: response["statusCode"] = 400 - response['body'] = {"error": "Bad request: missing header"} + response["body"] = json.dumps({"error": "Bad request: Missing headers"}) return response query_parameters = event['queryStringParameters'] header = event['headers'] try: - session_id = header["Session-Id"] - except: - session_id = header["session-id"] + session_id = header.get("Session-Id", header.get("session-id")) + except Exception: + response["statusCode"] = 400 + response["body"] = json.dumps({"error": "Bad request: Session-ID header not found"}) + return response + input_json = { - "searchTerm": query_parameters["searchTerm"], - "pageNumber": query_parameters["pageNumber"], - "refreshResults": query_parameters["refreshResults"], + "searchTerm": query_parameters.get("searchTerm"), + "pageNumber": query_parameters.get("pageNumber"), + "refreshResults": query_parameters.get("refreshResults"), "sessionID": session_id, - "sortParams": query_parameters["sortParams"], - "filterParams": query_parameters["filterParams"] + "sortParams": query_parameters.get("sortParams"), + "filterParams": query_parameters.get("filterParams") } try: response_body = search(input_json) - except Exception as e: print(f"Exception in database query: {e}") response["statusCode"] = 500 - response['body'] = {"error": "Internal Server Error"} + response["body"] = json.dumps({"error": "Internal Server Error"}) return response - - - response["statusCode"] = 200 - response['body'] = json.dumps(response_body) - return response + response["body"] = json.dumps(response_body) + return response \ No newline at end of file