diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index fa99d64f..968cda5e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,7 +8,7 @@ updates:
- package-ecosystem: "npm" # See documentation for possible values
directories:
- "unicorn_contracts" # Location of package manifests
- - "unicorn_properties"
+ - "unicorn_approvals"
- "unicorn_web"
schedule:
interval: "monthly"
diff --git a/.github/workflows/auto_assign.yml b/.github/workflows/auto_assign.yml
index 57288678..093e194a 100644
--- a/.github/workflows/auto_assign.yml
+++ b/.github/workflows/auto_assign.yml
@@ -7,4 +7,4 @@ jobs:
add-reviews:
runs-on: ubuntu-latest
steps:
- - uses: kentaro-m/auto-assign-action@v1.2.5
\ No newline at end of file
+ - uses: kentaro-m/auto-assign-action@v2.0.0
\ No newline at end of file
diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml
index 433e9cc3..cb51cac0 100644
--- a/.github/workflows/build_test.yml
+++ b/.github/workflows/build_test.yml
@@ -6,7 +6,7 @@ on:
- '.github/workflows/*'
- 'unicorn_shared/**'
- 'unicorn_contracts/**'
- - 'unicorn_properties/**'
+ - 'unicorn_approvals/**'
- 'unicorn_web/**'
env:
AWS_REGION : "ap-southeast-2"
@@ -43,7 +43,7 @@ jobs:
strategy:
#max-parallel: 1
matrix:
- folder: [unicorn_contracts, unicorn_web, unicorn_properties]
+ folder: [unicorn_contracts, unicorn_web, unicorn_approvals]
steps:
- uses: actions/checkout@v4
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 6aee03e5..2da99daa 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -25,18 +25,18 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@2ca79b6fa8d3ec278944088b4aa5f46912db5d63 #v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
- # uses: github/codeql-action/autobuild@2ca79b6fa8d3ec278944088b4aa5f46912db5d63 #v2
+ # uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -49,4 +49,4 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@2ca79b6fa8d3ec278944088b4aa5f46912db5d63 #v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/label_pr_on_title.yml b/.github/workflows/label_pr_on_title.yml
index 3815a49e..e6ce47de 100644
--- a/.github/workflows/label_pr_on_title.yml
+++ b/.github/workflows/label_pr_on_title.yml
@@ -22,9 +22,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: "Label PR based on title"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }}
PR_TITLE: ${{ needs.get_pr_details.outputs.prTitle }}
diff --git a/.github/workflows/on_label_added.yml b/.github/workflows/on_label_added.yml
index e9180d80..ab04444c 100644
--- a/.github/workflows/on_label_added.yml
+++ b/.github/workflows/on_label_added.yml
@@ -23,10 +23,10 @@ jobs:
issues: write
pull-requests: write
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Maintenance: Persist state per PR as an artifact to avoid spam on label add
- name: "Suggest split large Pull Request"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }}
PR_ACTION: ${{ needs.get_pr_details.outputs.prAction }}
diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml
index cd97e1c3..2bce046e 100644
--- a/.github/workflows/on_merged_pr.yml
+++ b/.github/workflows/on_merged_pr.yml
@@ -20,9 +20,9 @@ jobs:
runs-on: ubuntu-latest
if: needs.get_pr_details.outputs.prIsMerged == 'true'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: "Label PR related issue for release"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }}
PR_BODY: ${{ needs.get_pr_details.outputs.prBody }}
diff --git a/.github/workflows/on_opened_pr.yml b/.github/workflows/on_opened_pr.yml
index 043ff962..9712a3f1 100644
--- a/.github/workflows/on_opened_pr.yml
+++ b/.github/workflows/on_opened_pr.yml
@@ -19,9 +19,9 @@ jobs:
needs: get_pr_details
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: "Ensure related issue is present"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
PR_BODY: ${{ needs.get_pr_details.outputs.prBody }}
PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }}
@@ -36,9 +36,9 @@ jobs:
needs: get_pr_details
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: "Ensure acknowledgement section is present"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
PR_BODY: ${{ needs.get_pr_details.outputs.prBody }}
PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }}
diff --git a/.github/workflows/record_pr.yml b/.github/workflows/record_pr.yml
index 70cbe154..7ef50e47 100644
--- a/.github/workflows/record_pr.yml
+++ b/.github/workflows/record_pr.yml
@@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: "Extract PR details"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
with:
script: |
const script = require('.github/scripts/save_pr_details.js')
diff --git a/.github/workflows/reusable_export_pr_details.yml b/.github/workflows/reusable_export_pr_details.yml
index a66c1cdd..e4ff73c5 100644
--- a/.github/workflows/reusable_export_pr_details.yml
+++ b/.github/workflows/reusable_export_pr_details.yml
@@ -53,9 +53,9 @@ jobs:
prIsMerged: ${{ steps.prIsMerged.outputs.prIsMerged }}
steps:
- name: Checkout repository # in case caller workflow doesn't checkout thus failing with file not found
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: "Download previously saved PR"
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
env:
WORKFLOW_ID: ${{ inputs.record_pr_workflow_id }}
# For security, we only download artifacts tied to the successful PR recording workflow
diff --git a/README.md b/README.md
index 783af415..d0040812 100755
--- a/README.md
+++ b/README.md
@@ -1,43 +1,38 @@
[](https://github.com/aws-samples/aws-serverless-developer-experience-workshop-typescript/actions/workflows/build_test.yml)
-
+# AWS Serverless Developer Experience workshop reference architecture (Typescript)
-# AWS Serverless Developer Experience workshop reference architecture (TypeScript)
+
-This repository contains the reference architecture for the AWS Serverless Developer Experience workshop.
+This repository contains the Typescript reference architecture for the AWS Serverless Developer Experience workshop.
-The AWS Serverless Developer Experience workshop provides you with an immersive experience as a serverless developer. The goal of this workshop is to provide you with hands-on experience building a serverless solution using the [**AWS Serverless Application Model (AWS SAM)**](https://aws.amazon.com/serverless/sam/) and **AWS SAM CLI**.
+The AWS Serverless Developer Experience Workshop is a comprehensive, hands-on training program designed to equip developers with practical serverless development skills using the [**AWS Serverless Application Model (AWS SAM)**](https://aws.amazon.com/serverless/sam/) and **AWS SAM CLI**.
-Along the way, you will learn about principals of distributed event-driven architectures, messaging patterns, orchestration, and observability and how to apply them in code. You will explore exciting open-source tools, the core features of Powertools for AWS Lambda, and simplified CI/CD deployments supported by AWS SAM Pipelines.
+The workshop employs a practical, code-centric approach, emphasizing direct implementation and real-world scenario exploration to ensure you develop serverless development skills across several critical areas including distributed event-driven architectures, messaging patterns, orchestration, and observability. You will explore open-source tools, [Powertools for AWS](https://powertools.aws.dev/), and simplified CI/CD deployments with AWS SAM Pipelines. By the end, you will be familiar with serverless developer workflows, microservice composition using AWS SAM, serverless development best practices, and applied event-driven architectures.
-At the end of this workshop, you will be familiar with Serverless developer workflows and microservice composition using AWS SAM, Serverless development best practices, and applied event-driven architectures.
+The 6-8 hour workshop assumes your practical development skills in Python, TypeScript, Java, or .NET, and familiarity with [Amazon API Gateway](https://aws.amazon.com/apigateway/), [AWS Lambda](https://aws.amazon.com/lambda/), [Amazon EventBridge](https://aws.amazon.com/eventbridge/), [AWS Step Functions](https://aws.amazon.com/step-functions/), and [Amazon DynamoDB](https://aws.amazon.com/dynamodb/).
## Introducing the Unicorn Properties architecture

-Our use case is based on a real estate company called **Unicorn Properties**.
-
-As a real estate agency, **Unicorn Properties** needs to manage the publishing of new property listings and sale contracts linked to individual properties, and provide a way for their customers to view approved property listings.
-
-To support their needs, Unicorn Properties have adopted a serverless, event-driven approach to designing their architecture. This architecture is centred around two primary domains: **Contracts** (managed by the Contracts Service) and **Properties** (managed by the Web and Properties Services).
+Real estate company **Unicorn Properties** needs to manage publishing of new property listings and sale contracts linked to individual properties, and provide a way for customers to view approved listings. They adopted a serverless, event-driven architecture with two primary domains: **Contracts** (managed by the Contracts Service) and **Properties** (managed by the Web and Approvals Services).
-The **Unicorn Contracts** service (namespace: `Unicorn.Contracts`) is a simplified service that manages the contractual relationship between a seller of a property and Unicorn Properties. Contracts are drawn up that define the property for sale, the terms and conditions that Unicorn Properties sets, and how much it will cost the seller to engage the services of the agency.
+**Unicorn Contracts** (using the `Unicorn.Contracts` namespace) service manages contractual relationships between property sellers and Unicorn Approvals, defining properties for sale, terms, and engagement costs.
-The **Unicorn Web** (namespace: `Unicorn.Web`) manages the details of a property listing to be published on the Unicorn Properties website. Every property listing has an address, a sale price, a description of the property, and some photos that members of the public can look at to get them interested in purchasing the property. Only properties that have been approved for publication can be made visible to the public.
+**Unicorn Approvals** (using the `Unicorn.Approvals` namespace) service approves property listings by implementing a workflow that checks for contract existence, content and image safety, and contract approval before publishing.
-The **Unicorn Properties** service (namespace: `Unicorn.Properties`) approves a property listings. This service implements a workflow that checks for the existence of a contract, makes sure that the content and the images are safe to publish, and finally checks that the contract has been approved. We don’t want to publish a property until we have an approved contract!
+**Unicorn Web** (using the `Unicorn.Web` namespace) manages property listing details (address, sale price, description, photos) to be published on the website, with only approved listings visible to the public.
-Have a go at building this architecture yourself! Head over to the [Serverless Developer Experience Workshop](https://catalog.workshops.aws/serverless-developer-experience) for more details.
## Credits
-Throughout this workshop we wanted to introduce you to some Open Source tools that can help you build serverless applications. This is not an exhaustive list, just a small selection of what we will be using in the workshop.
+This workshop introduces you to some open-source tools that can help you build serverless applications. This is not an exhaustive list, but a small selection of what you will be using in the workshop.
Many thanks to all the AWS teams and community builders who have contributed to this list:
-| Tools | Description | Download / Installation Instructions |
-| --------------------- | ----------- | --------------------------------------- |
-| cfn-lint | Validate AWS CloudFormation yaml/json templates against the AWS CloudFormation Resource Specification and additional checks. | https://github.com/aws-cloudformation/cfn-lint |
-| cfn-lint-serverless | Compilation of rules to validate infrastructure-as-code templates against recommended practices for serverless applications. | https://github.com/awslabs/serverless-rules |
-| @mhlabs/iam-policies-cli| CLI for generating AWS IAM policy documents or SAM policy templates based on the JSON definition used in the AWS Policy Generator. | https://github.com/mhlabs/iam-policies-cli |
-| @mhlabs/evb-cli | Pattern generator and debugging tool for Amazon EventBridge | https://github.com/mhlabs/evb-cli |
+| Tools | Description | Download / Installation Instructions |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
+| cfn-lint | Validate AWS CloudFormation yaml/json templates against the AWS CloudFormation Resource Specification and additional checks. | https://github.com/aws-cloudformation/cfn-lint |
+| cfn-lint-serverless | Compilation of rules to validate infrastructure-as-code templates against recommended practices for serverless applications. | https://github.com/awslabs/serverless-rules |
+| @mhlabs/iam-policies-cli | CLI for generating AWS IAM policy documents or SAM policy templates based on the JSON definition used in the AWS Policy Generator. | https://github.com/mhlabs/iam-policies-cli |
+| @mhlabs/evb-cli | Pattern generator and debugging tool for Amazon EventBridge | https://github.com/mhlabs/evb-cli |
diff --git a/docs/architecture.png b/docs/architecture.png
index 1e741f21..903363bb 100644
Binary files a/docs/architecture.png and b/docs/architecture.png differ
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 641822ba..b6962d76 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -115,7 +115,7 @@ importers:
specifier: ^8.32.1
version: 8.32.1(eslint@9.27.0)(typescript@5.8.3)
- unicorn_properties:
+ unicorn_approvals:
dependencies:
'@aws-lambda-powertools/commons':
specifier: ^2.20.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index b63f84e8..3005b396 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,5 +1,5 @@
packages:
- unicorn_shared
- unicorn_contracts
- - unicorn_properties
+ - unicorn_approvals
- unicorn_web
diff --git a/unicorn_properties/.gitignore b/unicorn_approvals/.gitignore
similarity index 100%
rename from unicorn_properties/.gitignore
rename to unicorn_approvals/.gitignore
diff --git a/unicorn_properties/.npmignore b/unicorn_approvals/.npmignore
similarity index 100%
rename from unicorn_properties/.npmignore
rename to unicorn_approvals/.npmignore
diff --git a/unicorn_properties/.prettierignore b/unicorn_approvals/.prettierignore
similarity index 100%
rename from unicorn_properties/.prettierignore
rename to unicorn_approvals/.prettierignore
diff --git a/unicorn_properties/.prettierrc.js b/unicorn_approvals/.prettierrc.js
similarity index 100%
rename from unicorn_properties/.prettierrc.js
rename to unicorn_approvals/.prettierrc.js
diff --git a/unicorn_properties/Makefile b/unicorn_approvals/Makefile
similarity index 94%
rename from unicorn_properties/Makefile
rename to unicorn_approvals/Makefile
index 7df61aaa..35619e23 100644
--- a/unicorn_properties/Makefile
+++ b/unicorn_approvals/Makefile
@@ -1,9 +1,9 @@
#### Global Variables
-stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.yaml)
+stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.toml)
#### Build/Deploy Tasks
-ci: deps clean build deploy
+ci: deps build deploy
deps:
pnpm i
diff --git a/unicorn_approvals/README.md b/unicorn_approvals/README.md
new file mode 100644
index 00000000..78cbc75d
--- /dev/null
+++ b/unicorn_approvals/README.md
@@ -0,0 +1,15 @@
+# Developing Unicorn Approvals
+
+
+
+## Architecture overview
+
+**Unicorn Approvals** uses an AWS Step Functions state machine to approve property listings for Unicorn Web. The workflow checks for contract information, description sentiment and safe images, and verifies the contract is approved before approving the listing. It publishes the result via the `PublicationEvaluationCompleted` event.
+
+A Unicorn Properties agent initiates the workflow by requesting to approve a listing, generating a `PublicationApprovalRequested` event with property information. To decouple from the Contracts Service, the Approvals service maintains a local copy of contract status by consuming the ContractStatusChanged event.
+
+The workflow checks the contract state. If the contract is in the WaitForContractApproval state, it updates the contract status for the property with its task token, triggering a DynamoDB stream event. The Property Approval Sync function handles these events and passes the task token back to the state machine based on the contract state.
+
+If the workflow completes successfully, it emits a PublicationEvaluationCompleted event with an **approved** or **declined** evaluation result, which Unicorn Web listens to update its publication flag.
+
+**Note:** Upon deleting the CloudFormation stack for this service, check if the `ApprovalStateMachine` StepFunction doesn't have any executions in `RUNNING` state. If there are, cancel those execution prior to deleting the CloudFormation stack.
\ No newline at end of file
diff --git a/unicorn_properties/eslint.config.mjs b/unicorn_approvals/eslint.config.mjs
similarity index 100%
rename from unicorn_properties/eslint.config.mjs
rename to unicorn_approvals/eslint.config.mjs
diff --git a/unicorn_properties/integration/PublicationEvaluationCompleted.json b/unicorn_approvals/integration/PublicationEvaluationCompleted.json
similarity index 100%
rename from unicorn_properties/integration/PublicationEvaluationCompleted.json
rename to unicorn_approvals/integration/PublicationEvaluationCompleted.json
diff --git a/unicorn_properties/integration/event-schemas.yaml b/unicorn_approvals/integration/event-schemas.yaml
similarity index 95%
rename from unicorn_properties/integration/event-schemas.yaml
rename to unicorn_approvals/integration/event-schemas.yaml
index 9a9f318c..1817b39d 100644
--- a/unicorn_properties/integration/event-schemas.yaml
+++ b/unicorn_approvals/integration/event-schemas.yaml
@@ -18,7 +18,7 @@ Resources:
Properties:
Description: 'Event schemas for Unicorn Properties'
RegistryName:
- Fn::Sub: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}-${Stage}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}-${Stage}"
EventRegistryPolicy:
Type: AWS::EventSchemas::RegistryPolicy
@@ -52,7 +52,7 @@ Resources:
RegistryName:
Fn::GetAtt: EventRegistry.RegistryName
SchemaName:
- Fn::Sub: '{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}@PublicationEvaluationCompleted'
+ Fn::Sub: '{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}@PublicationEvaluationCompleted'
Description: 'The schema for when a property evaluation is completed'
Content:
Fn::Sub: |
diff --git a/unicorn_properties/integration/subscriber-policies.yaml b/unicorn_approvals/integration/subscriber-policies.yaml
similarity index 89%
rename from unicorn_properties/integration/subscriber-policies.yaml
rename to unicorn_approvals/integration/subscriber-policies.yaml
index 6dfd3b22..87b97703 100644
--- a/unicorn_properties/integration/subscriber-policies.yaml
+++ b/unicorn_approvals/integration/subscriber-policies.yaml
@@ -20,7 +20,7 @@ Resources:
Type: AWS::Events::EventBusPolicy
Properties:
EventBusName:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBus}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBus}}"
StatementId:
Fn::Sub: "OnlyRulesForPropertiesServiceEvents-${Stage}"
Statement:
@@ -40,12 +40,12 @@ Resources:
- Fn::Sub:
- arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${eventBusName}/*
- eventBusName:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBus}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBus}}"
Condition:
StringEqualsIfExists:
"events:creatorAccount": "${aws:PrincipalAccount}"
StringEquals:
"events:source":
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
"Null":
"events:source": "false"
diff --git a/unicorn_properties/integration/subscriptions.yaml b/unicorn_approvals/integration/subscriptions.yaml
similarity index 88%
rename from unicorn_properties/integration/subscriptions.yaml
rename to unicorn_approvals/integration/subscriptions.yaml
index acdf7a0a..3a35e1ca 100644
--- a/unicorn_properties/integration/subscriptions.yaml
+++ b/unicorn_approvals/integration/subscriptions.yaml
@@ -18,7 +18,7 @@ Resources:
ContractStatusChangedSubscriptionRule:
Type: AWS::Events::Rule
Properties:
- Name: unicorn.properties-ContractStatusChanged
+ Name: unicorn.approvals-ContractStatusChanged
Description: Contract Status Changed subscription
EventBusName:
Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornContractsEventBusArn}}"
@@ -31,7 +31,7 @@ Resources:
Targets:
- Id: SendEventTo
Arn:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBusArn}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBusArn}}"
RoleArn:
Fn::GetAtt: [ UnicornPropertiesSubscriptionRole, Arn ]
@@ -39,7 +39,7 @@ Resources:
PublicationApprovalRequestedSubscriptionRule:
Type: AWS::Events::Rule
Properties:
- Name: unicorn.properties-PublicationApprovalRequested
+ Name: unicorn.approvals-PublicationApprovalRequested
Description: Publication evaluation completed subscription
EventBusName:
Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornWebEventBusArn}}"
@@ -52,13 +52,13 @@ Resources:
Targets:
- Id: SendEventTo
Arn:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBusArn}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBusArn}}"
RoleArn:
Fn::GetAtt: [ UnicornPropertiesSubscriptionRole, Arn ]
# This IAM role allows EventBridge to assume the permissions necessary to send events
- # from the publishing event bus, to the subscribing event bus (UnicornPropertiesEventBusArn)
+ # from the publishing event bus, to the subscribing event bus (UnicornApprovalsEventBusArn)
UnicornPropertiesSubscriptionRole:
Type: AWS::IAM::Role
Properties:
@@ -76,7 +76,7 @@ Resources:
- Effect: Allow
Action: events:PutEvents
Resource:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBusArn}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBusArn}}"
Outputs:
ContractStatusChangedSubscription:
diff --git a/unicorn_properties/jest.config.js b/unicorn_approvals/jest.config.js
similarity index 100%
rename from unicorn_properties/jest.config.js
rename to unicorn_approvals/jest.config.js
diff --git a/unicorn_properties/package.json b/unicorn_approvals/package.json
similarity index 100%
rename from unicorn_properties/package.json
rename to unicorn_approvals/package.json
diff --git a/unicorn_properties/samconfig.toml b/unicorn_approvals/samconfig.toml
similarity index 87%
rename from unicorn_properties/samconfig.toml
rename to unicorn_approvals/samconfig.toml
index 80abe0b2..e8b9e83a 100644
--- a/unicorn_properties/samconfig.toml
+++ b/unicorn_approvals/samconfig.toml
@@ -1,8 +1,8 @@
version = 0.1
[default.global.parameters]
-stack_name = "uni-prop-local-properties"
-s3_prefix = "uni-prop-local-properties"
+stack_name = "uni-prop-local-approvals"
+s3_prefix = "uni-prop-local-approvals"
resolve_s3 = true
resolve_image_repositories = true
diff --git a/unicorn_properties/src/properties_service/contractStatusChangedEventHandler.ts b/unicorn_approvals/src/approvals_service/contractStatusChangedEventHandler.ts
similarity index 98%
rename from unicorn_properties/src/properties_service/contractStatusChangedEventHandler.ts
rename to unicorn_approvals/src/approvals_service/contractStatusChangedEventHandler.ts
index db0c985e..23634ef7 100644
--- a/unicorn_properties/src/properties_service/contractStatusChangedEventHandler.ts
+++ b/unicorn_approvals/src/approvals_service/contractStatusChangedEventHandler.ts
@@ -15,7 +15,7 @@ import { Marshaller } from '../schema/unicorn_contracts/contractstatuschanged/ma
// Empty configuration for DynamoDB
const ddbClient = new DynamoDBClient({});
-const DDB_TABLE = process.env.DYNAMODB_TABLE ?? 'ContractStatusTable';
+const DDB_TABLE = process.env.CONTRACT_STATUS_TABLE ?? 'ContractStatusTable';
export interface ContractStatusError extends Error {
contract_id: string;
diff --git a/unicorn_properties/src/properties_service/powertools.ts b/unicorn_approvals/src/approvals_service/powertools.ts
similarity index 100%
rename from unicorn_properties/src/properties_service/powertools.ts
rename to unicorn_approvals/src/approvals_service/powertools.ts
diff --git a/unicorn_properties/src/properties_service/propertiesApprovalSyncFunction.ts b/unicorn_approvals/src/approvals_service/propertiesApprovalSyncFunction.ts
similarity index 100%
rename from unicorn_properties/src/properties_service/propertiesApprovalSyncFunction.ts
rename to unicorn_approvals/src/approvals_service/propertiesApprovalSyncFunction.ts
diff --git a/unicorn_properties/src/properties_service/waitForContractApprovalFunction.ts b/unicorn_approvals/src/approvals_service/waitForContractApprovalFunction.ts
similarity index 98%
rename from unicorn_properties/src/properties_service/waitForContractApprovalFunction.ts
rename to unicorn_approvals/src/approvals_service/waitForContractApprovalFunction.ts
index 55a4a596..7b449417 100644
--- a/unicorn_properties/src/properties_service/waitForContractApprovalFunction.ts
+++ b/unicorn_approvals/src/approvals_service/waitForContractApprovalFunction.ts
@@ -16,7 +16,7 @@ import { unmarshall } from '@aws-sdk/util-dynamodb';
// Empty configuration for DynamoDB
const ddbClient = new DynamoDBClient({});
-const DDB_TABLE = process.env.DYNAMODB_TABLE ?? 'ContractStatusTable';
+const DDB_TABLE = process.env.CONTRACT_STATUS_TABLE ?? 'ContractStatusTable';
// Empty configuration for SFN
// const sfnClient = new SFNClient({});
diff --git a/unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/AWSEvent.ts b/unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/AWSEvent.ts
similarity index 100%
rename from unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/AWSEvent.ts
rename to unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/AWSEvent.ts
diff --git a/unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/ContractStatusChanged.ts b/unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/ContractStatusChanged.ts
similarity index 100%
rename from unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/ContractStatusChanged.ts
rename to unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/ContractStatusChanged.ts
diff --git a/unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/marshaller/Marshaller.ts b/unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/marshaller/Marshaller.ts
similarity index 100%
rename from unicorn_properties/src/schema/unicorn_contracts/contractstatuschanged/marshaller/Marshaller.ts
rename to unicorn_approvals/src/schema/unicorn_contracts/contractstatuschanged/marshaller/Marshaller.ts
diff --git a/unicorn_properties/src/state_machine/property_approval.asl.yaml b/unicorn_approvals/src/state_machine/property_approval.asl.yaml
similarity index 100%
rename from unicorn_properties/src/state_machine/property_approval.asl.yaml
rename to unicorn_approvals/src/state_machine/property_approval.asl.yaml
diff --git a/unicorn_properties/template.yaml b/unicorn_approvals/template.yaml
similarity index 81%
rename from unicorn_properties/template.yaml
rename to unicorn_approvals/template.yaml
index fa35ff2b..54107378 100644
--- a/unicorn_properties/template.yaml
+++ b/unicorn_approvals/template.yaml
@@ -4,7 +4,7 @@ AWSTemplateFormatVersion: "2010-09-09"
Transform:
- AWS::Serverless-2016-10-31
Description: >
- Unicorn Properties Service. Validate the content, images and contract of property listings.
+ Unicorn Approvals Service. Validate the content, images and contract of property listings.
Metadata:
cfn-lint:
@@ -16,7 +16,6 @@ Metadata:
- WS2001 # Rule disabled because check does not support !ToJsonString transform
- ES1001 # Rule disabled because our Lambda functions don't need DestinationConfig.OnFailure
- W3002 # Rule disabled as nested templates are being packaged
- - E3030 # Rule disabled due to using cfn-lint-serverless rules v0.3
Parameters:
Stage:
@@ -53,48 +52,48 @@ Globals:
Environment:
Variables:
CONTRACT_STATUS_TABLE: !Ref ContractStatusTable
- EVENT_BUS: !Ref UnicornPropertiesEventBus
- SERVICE_NAMESPACE: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ EVENT_BUS: !Ref UnicornApprovalsEventBus
+ SERVICE_NAMESPACE: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
POWERTOOLS_LOGGER_CASE: PascalCase
- POWERTOOLS_SERVICE_NAME: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ POWERTOOLS_SERVICE_NAME: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
POWERTOOLS_TRACE_DISABLED: "false" # Explicitly disables tracing, default
POWERTOOLS_LOGGER_LOG_EVENT: !If [IsProd, "false", "true"] # Logs incoming event, default
POWERTOOLS_LOGGER_SAMPLE_RATE: !If [IsProd, "0.1", "0"] # Debug log sampling percentage, default
- POWERTOOLS_METRICS_NAMESPACE: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ POWERTOOLS_METRICS_NAMESPACE: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
POWERTOOLS_LOG_LEVEL: INFO # Log level for Logger (INFO, DEBUG, etc.), default
LOG_LEVEL: INFO # Log level for Logger
Tags:
stage: !Ref Stage
project: !FindInMap [Constants, ProjectName, Value]
- namespace: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ namespace: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
Resources:
#### SSM PARAMETERS
# Services share their event bus name and arn
- UnicornPropertiesEventBusNameParam:
+ UnicornApprovalsEventBusNameParam:
Type: AWS::SSM::Parameter
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Type: String
- Name: !Sub /uni-prop/${Stage}/UnicornPropertiesEventBus
- Value: !GetAtt UnicornPropertiesEventBus.Name
+ Name: !Sub /uni-prop/${Stage}/UnicornApprovalsEventBus
+ Value: !GetAtt UnicornApprovalsEventBus.Name
- UnicornPropertiesEventBusArnParam:
+ UnicornApprovalsEventBusArnParam:
Type: AWS::SSM::Parameter
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Type: String
- Name: !Sub /uni-prop/${Stage}/UnicornPropertiesEventBusArn
- Value: !GetAtt UnicornPropertiesEventBus.Arn
+ Name: !Sub /uni-prop/${Stage}/UnicornApprovalsEventBusArn
+ Value: !GetAtt UnicornApprovalsEventBus.Arn
#### LAMBDA FUNCTIONS
# Listens to ContractStatusChanged events from EventBridge
ContractStatusChangedHandlerFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: src/properties_service
+ CodeUri: src/approvals_service
Handler: contractStatusChangedEventHandler.lambdaHandler
Policies:
- DynamoDBWritePolicy:
@@ -105,8 +104,8 @@ Resources:
StatusChangedEvent:
Type: EventBridgeRule
Properties:
- RuleName: unicorn.properties-ContractStatusChanged
- EventBusName: !GetAtt UnicornPropertiesEventBus.Name
+ RuleName: unicorn.approvals-ContractStatusChanged
+ EventBusName: !GetAtt UnicornApprovalsEventBus.Name
Pattern:
source:
- "{{resolve:ssm:/uni-prop/UnicornContractsNamespace}}"
@@ -116,12 +115,12 @@ Resources:
MaximumRetryAttempts: 5
MaximumEventAgeInSeconds: 900
DeadLetterConfig:
- Arn: !GetAtt PropertiesEventBusRuleDLQ.Arn
+ Arn: !GetAtt ApprovalsEventBusRuleDLQ.Arn
EventInvokeConfig:
DestinationConfig:
OnFailure:
Type: SQS
- Destination: !GetAtt PropertiesServiceDLQ.Arn
+ Destination: !GetAtt ApprovalsServiceDLQ.Arn
Metadata:
# Manage esbuild properties
BuildMethod: esbuild
@@ -145,7 +144,7 @@ Resources:
PropertiesApprovalSyncFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: src/properties_service
+ CodeUri: src/approvals_service
Handler: propertiesApprovalSyncFunction.lambdaHandler
Policies:
- DynamoDBReadPolicy:
@@ -155,7 +154,7 @@ Resources:
StreamName:
!Select [3, !Split ["/", !GetAtt ContractStatusTable.StreamArn]]
- SQSSendMessagePolicy:
- QueueName: !GetAtt PropertiesServiceDLQ.QueueName
+ QueueName: !GetAtt ApprovalsServiceDLQ.QueueName
- Statement:
- Effect: Allow
Action:
@@ -172,12 +171,12 @@ Resources:
MaximumRetryAttempts: 3
DestinationConfig:
OnFailure:
- Destination: !GetAtt PropertiesServiceDLQ.Arn
+ Destination: !GetAtt ApprovalsServiceDLQ.Arn
EventInvokeConfig:
DestinationConfig:
OnFailure:
Type: SQS
- Destination: !GetAtt PropertiesServiceDLQ.Arn
+ Destination: !GetAtt ApprovalsServiceDLQ.Arn
Metadata:
# Manage esbuild properties
BuildMethod: esbuild
@@ -201,7 +200,7 @@ Resources:
WaitForContractApprovalFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: src/properties_service
+ CodeUri: src/approvals_service
Handler: waitForContractApprovalFunction.lambdaHandler
Policies:
- DynamoDBCrudPolicy:
@@ -246,7 +245,7 @@ Resources:
- S3ReadPolicy:
BucketName: !Sub "{{resolve:ssm:/uni-prop/${Stage}/ImagesBucket}}"
- EventBridgePutEventsPolicy:
- EventBusName: !GetAtt UnicornPropertiesEventBus.Name
+ EventBusName: !GetAtt UnicornApprovalsEventBus.Name
- Statement:
- Effect: Allow
Action:
@@ -270,8 +269,8 @@ Resources:
PublicationApprovalRequestedEvent:
Type: EventBridgeRule
Properties:
- RuleName: unicorn.properties-PublicationApprovalRequested
- EventBusName: !GetAtt UnicornPropertiesEventBus.Name
+ RuleName: unicorn.approvals-PublicationApprovalRequested
+ EventBusName: !GetAtt UnicornApprovalsEventBus.Name
Pattern:
source:
- "{{resolve:ssm:/uni-prop/UnicornWebNamespace}}"
@@ -282,13 +281,13 @@ Resources:
MaximumEventAgeInSeconds: 900
DeadLetterConfig:
Type: SQS
- Destination: !GetAtt PropertiesServiceDLQ.Arn
+ Destination: !GetAtt ApprovalsServiceDLQ.Arn
DefinitionSubstitutions:
WaitForContractApprovalArn: !GetAtt WaitForContractApprovalFunction.Arn
TableName: !Ref ContractStatusTable
ImageUploadBucketName: !Sub "{{resolve:ssm:/uni-prop/${Stage}/ImagesBucket}}"
- EventBusName: !GetAtt UnicornPropertiesEventBus.Name
- ServiceName: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ EventBusName: !GetAtt UnicornApprovalsEventBus.Name
+ ServiceName: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
# Store ApprovalStateMachineLogGroup workflow execution logs
ApprovalStateMachineLogGroup:
@@ -301,7 +300,7 @@ Resources:
#### DEAD LETTER QUEUES
# Store EventBridge events that failed to be DELIVERED to ContractStatusChangedHandlerFunction
- PropertiesEventBusRuleDLQ:
+ ApprovalsEventBusRuleDLQ:
Type: AWS::SQS::Queue
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
@@ -312,12 +311,12 @@ Resources:
- Key: project
Value: !FindInMap [Constants, ProjectName, Value]
- Key: namespace
- Value: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ Value: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- Key: stage
Value: !Ref Stage
- # Store failed INVOCATIONS to each Lambda function in Unicorn Properties Service
- PropertiesServiceDLQ:
+ # Store failed INVOCATIONS to each Lambda function in Unicorn Approvals Service
+ ApprovalsServiceDLQ:
Type: AWS::SQS::Queue
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
@@ -328,7 +327,7 @@ Resources:
- Key: project
Value: !FindInMap [Constants, ProjectName, Value]
- Key: namespace
- Value: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ Value: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- Key: stage
Value: !Ref Stage
@@ -351,62 +350,62 @@ Resources:
- Key: project
Value: !FindInMap [Constants, ProjectName, Value]
- Key: namespace
- Value: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ Value: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- Key: stage
Value: !Ref Stage
#### EVENT BUS
- # Event bus for Unicorn Properties Service, used to publish and consume events
- UnicornPropertiesEventBus:
+ # Event bus for Unicorn Approvals Service, used to publish and consume events
+ UnicornApprovalsEventBus:
Type: AWS::Events::EventBus
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
- Name: !Sub UnicornPropertiesBus-${Stage}
+ Name: !Sub UnicornApprovalsBus-${Stage}
- # Event bus policy to restrict who can publish events (should only be services from UnicornPropertiesNamespace)
- UnicornPropertiesEventsBusPublishPolicy:
+ # Event bus policy to restrict who can publish events (should only be services from UnicornApprovalsNamespace)
+ UnicornApprovalsEventsBusPublishPolicy:
Type: AWS::Events::EventBusPolicy
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
- EventBusName: !Ref UnicornPropertiesEventBus
- StatementId: !Sub OnlyPropertiesServiceCanPublishToEventBus-${Stage}
+ EventBusName: !Ref UnicornApprovalsEventBus
+ StatementId: !Sub OnlyApprovalsServiceCanPublishToEventBus-${Stage}
Statement:
Effect: Allow
Principal:
AWS:
- !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:root"
Action: events:PutEvents
- Resource: !GetAtt UnicornPropertiesEventBus.Arn
+ Resource: !GetAtt UnicornApprovalsEventBus.Arn
Condition:
StringEquals:
events:source:
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
# Catchall rule used for development purposes. Logs all events matching any of the services to CloudWatch Logs
- UnicornPropertiesCatchAllRule:
+ UnicornApprovalsCatchAllRule:
Type: AWS::Events::Rule
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
- Name: properties.catchall
+ Name: approvals.catchall
Description: Catchall rule used for development purposes.
- EventBusName: !Ref UnicornPropertiesEventBus
+ EventBusName: !Ref UnicornApprovalsEventBus
EventPattern:
account:
- !Ref AWS::AccountId
source:
- "{{resolve:ssm:/uni-prop/UnicornContractsNamespace}}"
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- "{{resolve:ssm:/uni-prop/UnicornWebNamespace}}"
State: ENABLED #You may want to disable this rule in production
Targets:
- - Arn: !GetAtt UnicornPropertiesCatchAllLogGroup.Arn
- Id: !Sub UnicornPropertiesCatchAllLogGroupTarget-${Stage}
+ - Arn: !GetAtt UnicornApprovalsCatchAllLogGroup.Arn
+ Id: !Sub UnicornApprovalsCatchAllLogGroupTarget-${Stage}
# CloudWatch log group used to catch all events
- UnicornPropertiesCatchAllLogGroup:
+ UnicornApprovalsCatchAllLogGroup:
Type: AWS::Logs::LogGroup
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
@@ -414,7 +413,7 @@ Resources:
LogGroupName: !Sub
- "/aws/events/${Stage}/${NS}-catchall"
- Stage: !Ref Stage
- NS: "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ NS: "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
RetentionInDays: !FindInMap [LogsRetentionPeriodMap, !Ref Stage, Days]
# Permissions to allow EventBridge to send logs to CloudWatch
@@ -440,14 +439,14 @@ Resources:
"logs:PutLogEvents"
],
"Resource": [
- "${UnicornPropertiesCatchAllLogGroup.Arn}"
+ "${UnicornApprovalsCatchAllLogGroup.Arn}"
]
}
]
}
#### CLOUDFORMATION NESTED STACKS
- # CloudFormation Stack with the Properties Service Event Registry and Schemas
+ # CloudFormation Stack with the Approvals Service Event Registry and Schemas
EventSchemasStack:
Type: AWS::Serverless::Application
UpdateReplacePolicy: Delete
@@ -457,25 +456,25 @@ Resources:
Parameters:
Stage: !Ref Stage
- # CloudFormation Stack with the Cross-service EventBus policy for Properties Service
+ # CloudFormation Stack with the Cross-service EventBus policy for Approvals Service
SubscriberPoliciesStack:
Type: AWS::Serverless::Application
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
DependsOn:
- - UnicornPropertiesEventBusNameParam
+ - UnicornApprovalsEventBusNameParam
Properties:
Location: "integration/subscriber-policies.yaml"
Parameters:
Stage: !Ref Stage
- # CloudFormation Stack with the Cross-service EventBus Rules for Properties Service
+ # CloudFormation Stack with the Cross-service EventBus Rules for Approvals Service
SubscriptionsStack:
Type: AWS::Serverless::Application
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
DependsOn:
- - UnicornPropertiesEventBusArnParam
+ - UnicornApprovalsEventBusArnParam
Properties:
Location: "integration/subscriptions.yaml"
Parameters:
@@ -510,13 +509,13 @@ Outputs:
Value: !Ref ApprovalStateMachine
#### EVENT BRIDGE OUTPUTS
- UnicornPropertiesEventBusName:
- Value: !GetAtt UnicornPropertiesEventBus.Name
+ UnicornApprovalsEventBusName:
+ Value: !GetAtt UnicornApprovalsEventBus.Name
#### CLOUDWATCH LOGS OUTPUTS
- UnicornPropertiesCatchAllLogGroupArn:
+ UnicornApprovalsCatchAllLogGroupArn:
Description: Log all events on the service's EventBridge Bus
- Value: !GetAtt UnicornPropertiesCatchAllLogGroup.Arn
+ Value: !GetAtt UnicornApprovalsCatchAllLogGroup.Arn
ApprovalStateMachineLogGroupName:
Value: !Ref ApprovalStateMachineLogGroup
\ No newline at end of file
diff --git a/unicorn_properties/tests/events/dbb_stream_events/contract_status_changed_draft.json b/unicorn_approvals/tests/events/dbb_stream_events/contract_status_changed_draft.json
similarity index 100%
rename from unicorn_properties/tests/events/dbb_stream_events/contract_status_changed_draft.json
rename to unicorn_approvals/tests/events/dbb_stream_events/contract_status_changed_draft.json
diff --git a/unicorn_properties/tests/events/dbb_stream_events/sfn_check_exists.json b/unicorn_approvals/tests/events/dbb_stream_events/sfn_check_exists.json
similarity index 100%
rename from unicorn_properties/tests/events/dbb_stream_events/sfn_check_exists.json
rename to unicorn_approvals/tests/events/dbb_stream_events/sfn_check_exists.json
diff --git a/unicorn_properties/tests/events/dbb_stream_events/sfn_wait_approval.json b/unicorn_approvals/tests/events/dbb_stream_events/sfn_wait_approval.json
similarity index 100%
rename from unicorn_properties/tests/events/dbb_stream_events/sfn_wait_approval.json
rename to unicorn_approvals/tests/events/dbb_stream_events/sfn_wait_approval.json
diff --git a/unicorn_properties/tests/events/dbb_stream_events/status_approved_waiting_for_approval.json b/unicorn_approvals/tests/events/dbb_stream_events/status_approved_waiting_for_approval.json
similarity index 100%
rename from unicorn_properties/tests/events/dbb_stream_events/status_approved_waiting_for_approval.json
rename to unicorn_approvals/tests/events/dbb_stream_events/status_approved_waiting_for_approval.json
diff --git a/unicorn_properties/tests/events/dbb_stream_events/status_approved_with_no_workflow.json b/unicorn_approvals/tests/events/dbb_stream_events/status_approved_with_no_workflow.json
similarity index 100%
rename from unicorn_properties/tests/events/dbb_stream_events/status_approved_with_no_workflow.json
rename to unicorn_approvals/tests/events/dbb_stream_events/status_approved_with_no_workflow.json
diff --git a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json
similarity index 86%
rename from unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json
rename to unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json
index f46c6545..391b67fd 100644
--- a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json
+++ b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_approved.json
@@ -2,7 +2,7 @@
{
"DetailType": "ContractStatusChanged",
"Source": "unicorn.contracts",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{ \"contract_last_modified_on\": \"10/08/2022 19:56:30\", \"contract_id\": \"f2bedc80-3dc8-4544-9140-9b606d71a6ee\", \"property_id\": \"usa/anytown/main-street/111\", \"contract_status\": \"APPROVED\" }"
}
]
\ No newline at end of file
diff --git a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json
similarity index 85%
rename from unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json
rename to unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json
index c975ddf9..006e110f 100644
--- a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json
+++ b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_1_draft.json
@@ -2,7 +2,7 @@
{
"DetailType": "ContractStatusChanged",
"Source": "unicorn.contracts",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{ \"contract_last_modified_on\": \"10/08/2022 19:56:30\", \"contract_id\": \"f2bedc80-3dc8-4544-9140-9b606d71a6ee\", \"property_id\": \"usa/anytown/main-street/111\", \"contract_status\": \"DRAFT\" }"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json
similarity index 86%
rename from unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json
rename to unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json
index 3e36ca34..24be4d08 100644
--- a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json
+++ b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_approved.json
@@ -2,7 +2,7 @@
{
"DetailType": "ContractStatusChanged",
"Source": "unicorn.contracts",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{ \"contract_last_modified_on\": \"10/08/2022 19:56:30\", \"contract_id\": \"9183453b-d284-4466-a2d9-f00b1d569ad7\", \"property_id\": \"usa/anytown/main-street/222\", \"contract_status\": \"APPROVED\" }"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json
similarity index 85%
rename from unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json
rename to unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json
index de4409fb..85271f71 100644
--- a/unicorn_properties/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json
+++ b/unicorn_approvals/tests/events/eventbridge/contract_status_changed_event_contract_2_draft.json
@@ -2,7 +2,7 @@
{
"DetailType": "ContractStatusChanged",
"Source": "unicorn.contracts",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{ \"contract_last_modified_on\": \"10/08/2022 19:56:30\", \"contract_id\": \"9183453b-d284-4466-a2d9-f00b1d569ad7\", \"property_id\": \"usa/anytown/main-street/222\", \"contract_status\": \"DRAFT\" }"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event.json
similarity index 100%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event.json
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_all_good.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_all_good.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_all_good.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_all_good.json
index 6d05077f..ff30e2c3 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_all_good.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_all_good.json
@@ -2,7 +2,7 @@
{
"DetailType": "PublicationApprovalRequested",
"Source": "unicorn.web",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{\"property_id\":\"usa/anytown/main-street/222\",\"address\":{\"country\":\"USA\",\"city\":\"Anytown\",\"street\":\"Main Street\",\"number\":222},\"description\":\"This classic Anytown estate comes with a covetable lake view. The romantic and comfortable backyard is the perfect setting for unicorn get-togethers. The open concept Main Stable is fully equipped with all the desired amenities. Second floor features 6 straw bales including large Rainbow Suite with private training pool terrace and Jr Sparkles Suite.\",\"contract\":\"sale\",\"listprice\":200,\"currency\":\"SPL\",\"images\":[\"property_images/prop1_exterior1.jpg\",\"property_images/prop1_interior1.jpg\",\"property_images/prop1_interior2.jpg\",\"property_images/prop1_interior3.jpg\"]}"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json
index ce594c12..14fc8c42 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_description.json
@@ -2,7 +2,7 @@
{
"DetailType": "PublicationApprovalRequested",
"Source": "unicorn.web",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{\"property_id\":\"usa/anytown/main-street/111\",\"address\":{\"country\":\"USA\",\"city\":\"Anytown\",\"street\":\"Main Street\",\"number\":111},\"description\":\"This is a property for goblins. The property has the worst quality and is atrocious when it comes to design. The property is not clean whatsoever, and will make any property owner have buyers' remorse as soon the property is bought. Keep away from this property as much as possible!\",\"contract\":\"sale\",\"listprice\":200,\"currency\":\"SPL\",\"images\":[\"property_images/prop1_exterior1.jpg\",\"property_images/prop1_interior1.jpg\",\"property_images/prop1_interior2.jpg\",\"property_images/prop1_interior3.jpg\"]}"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json
index eb9c5ab7..3e720412 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_inappropriate_images.json
@@ -2,7 +2,7 @@
{
"DetailType": "PublicationApprovalRequested",
"Source": "unicorn.web",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{\"property_id\":\"usa/anytown/main-street/111\",\"address\":{\"country\":\"USA\",\"city\":\"Anytown\",\"street\":\"Main Street\",\"number\":111},\"description\":\"This classic Anytown estate comes with a covetable lake view. The romantic and comfortable backyard is the perfect setting for unicorn get-togethers. The open concept Main Stable is fully equipped with all the desired amenities. Second floor features 6 straw bales including large Rainbow Suite with private training pool terrace and Jr Sparkles Suite.\",\"contract\":\"sale\",\"listprice\":200,\"currency\":\"SPL\",\"images\":[\"property_images/prop1_exterior1.jpg\",\"property_images/prop1_interior1.jpg\",\"property_images/prop1_interior2.jpg\",\"property_images/prop1_interior3.jpg\",\"property_images/prop1_interior4-bad.jpg\"]}"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json
index 70662197..d5f137dd 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_non_existing_contract.json
@@ -2,7 +2,7 @@
{
"DetailType": "PublicationApprovalRequested",
"Source": "unicorn.web",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{\"property_id\":\"usa/anytown/main-street/333\",\"address\":{\"country\":\"USA\",\"city\":\"Anytown\",\"street\":\"Main Street\",\"number\":333},\"description\":\"This classic Anytown estate comes with a covetable lake view. The romantic and comfortable backyard is the perfect setting for unicorn get-togethers. The open concept Main Stable is fully equipped with all the desired amenities. Second floor features 6 straw bales including large Rainbow Suite with private training pool terrace and Jr Sparkles Suite.\",\"contract\":\"sale\",\"listprice\":200,\"currency\":\"SPL\",\"images\":[\"property_images/prop1_exterior1.jpg\",\"property_images/prop1_interior1.jpg\",\"property_images/prop1_interior2.jpg\",\"property_images/prop1_interior3.jpg\"]}"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json
rename to unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json
index 8f804ab9..ee5206a0 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_approval_requested_event_pause_workflow.json
@@ -2,7 +2,7 @@
{
"DetailType": "PublicationApprovalRequested",
"Source": "unicorn.web",
- "EventBusName": "UnicornPropertiesBus-local",
+ "EventBusName": "UnicornApprovalsBus-local",
"Detail": "{\"property_id\":\"usa/anytown/main-street/111\",\"address\":{\"country\":\"USA\",\"city\":\"Anytown\",\"street\":\"Main Street\",\"number\":111},\"description\":\"This classic Anytown estate comes with a covetable lake view. The romantic and comfortable backyard is the perfect setting for unicorn get-togethers. The open concept Main Stable is fully equipped with all the desired amenities. Second floor features 6 straw bales including large Rainbow Suite with private training pool terrace and Jr Sparkles Suite.\",\"contract\":\"sale\",\"listprice\":200,\"currency\":\"SPL\",\"images\":[\"property_images/prop1_exterior1.jpg\",\"property_images/prop1_interior1.jpg\",\"property_images/prop1_interior2.jpg\",\"property_images/prop1_interior3.jpg\"]}"
}
]
diff --git a/unicorn_properties/tests/events/eventbridge/publication_evaluation_completed_event.json b/unicorn_approvals/tests/events/eventbridge/publication_evaluation_completed_event.json
similarity index 92%
rename from unicorn_properties/tests/events/eventbridge/publication_evaluation_completed_event.json
rename to unicorn_approvals/tests/events/eventbridge/publication_evaluation_completed_event.json
index b96c3a64..aeeabc01 100644
--- a/unicorn_properties/tests/events/eventbridge/publication_evaluation_completed_event.json
+++ b/unicorn_approvals/tests/events/eventbridge/publication_evaluation_completed_event.json
@@ -2,7 +2,7 @@
"version": "0",
"id": "f849f683-76e1-1c84-669d-544a9828dfef",
"detail-type": "PublicationEvaluationCompleted",
- "source": "unicorn.properties",
+ "source": "unicorn.approvals",
"account": "123456789012",
"time": "2022-08-16T06:33:05Z",
"region": "ap-southeast-2",
diff --git a/unicorn_properties/tests/events/eventbridge/put_event_property_approval_requested.json b/unicorn_approvals/tests/events/eventbridge/put_event_property_approval_requested.json
similarity index 94%
rename from unicorn_properties/tests/events/eventbridge/put_event_property_approval_requested.json
rename to unicorn_approvals/tests/events/eventbridge/put_event_property_approval_requested.json
index ee6128d4..3456a5ad 100644
--- a/unicorn_properties/tests/events/eventbridge/put_event_property_approval_requested.json
+++ b/unicorn_approvals/tests/events/eventbridge/put_event_property_approval_requested.json
@@ -3,6 +3,6 @@
"Source": "unicorn.web",
"Detail": "{ \"property_id\": \"usa/anytown/main-street/111\", \"country\": \"USA\", \"city\": \"Anytown\", \"street\": \"Main Street\", \"number\": 111, \"description\": \"This classic Anytown estate comes with a covetable lake view. The romantic and comfortable backyard is the perfect setting for unicorn get-togethers. The open concept Main Stable is fully equipped with all the desired amenities. Second floor features 6 straw bales including large Rainbow Suite with private training pool terrace and Jr Sparkles Suite.\", \"contract\": \"sale\", \"listprice\": 200, \"currency\": \"SPL\", \"images\": [ \"property_images/prop1_exterior1.jpg\", \"property_images/prop1_interior1.jpg\", \"property_images/prop1_interior2.jpg\", \"property_images/prop1_interior3.jpg\", \"property_images/prop1_interior4-bad.jpg\" ] }",
"DetailType": "PublicationApprovalRequested",
- "EventBusName": "UnicornPropertiesBus-local"
+ "EventBusName": "UnicornApprovalsBus-local"
}
]
diff --git a/unicorn_properties/tests/events/lambda/content_integrity_validator_function_success.json b/unicorn_approvals/tests/events/lambda/content_integrity_validator_function_success.json
similarity index 100%
rename from unicorn_properties/tests/events/lambda/content_integrity_validator_function_success.json
rename to unicorn_approvals/tests/events/lambda/content_integrity_validator_function_success.json
diff --git a/unicorn_properties/tests/events/lambda/contract_status_changed.json b/unicorn_approvals/tests/events/lambda/contract_status_changed.json
similarity index 100%
rename from unicorn_properties/tests/events/lambda/contract_status_changed.json
rename to unicorn_approvals/tests/events/lambda/contract_status_changed.json
diff --git a/unicorn_properties/tests/events/lambda/contract_status_checker.json b/unicorn_approvals/tests/events/lambda/contract_status_checker.json
similarity index 100%
rename from unicorn_properties/tests/events/lambda/contract_status_checker.json
rename to unicorn_approvals/tests/events/lambda/contract_status_checker.json
diff --git a/unicorn_properties/tests/events/lambda/wait_for_contract_approval_function.json b/unicorn_approvals/tests/events/lambda/wait_for_contract_approval_function.json
similarity index 100%
rename from unicorn_properties/tests/events/lambda/wait_for_contract_approval_function.json
rename to unicorn_approvals/tests/events/lambda/wait_for_contract_approval_function.json
diff --git a/unicorn_properties/tests/integration/approval_workflow.test.ts b/unicorn_approvals/tests/integration/approval_workflow.test.ts
similarity index 97%
rename from unicorn_properties/tests/integration/approval_workflow.test.ts
rename to unicorn_approvals/tests/integration/approval_workflow.test.ts
index b5283498..2c800b30 100644
--- a/unicorn_properties/tests/integration/approval_workflow.test.ts
+++ b/unicorn_approvals/tests/integration/approval_workflow.test.ts
@@ -57,7 +57,7 @@ describe('Tests that failed workflow', () => {
// Assert
const listExecutionsCommand = new ListExecutionsCommand({
stateMachineArn: await findOutputValue(
- 'uni-prop-local-properties-approval',
+ 'uni-prop-local-approvals',
'ApprovalStateMachineArn'
),
statusFilter: 'FAILED',
@@ -101,7 +101,7 @@ describe('Tests that failed workflow', () => {
// Assert
const listExecutionsCommand = new ListExecutionsCommand({
stateMachineArn: await findOutputValue(
- 'uni-prop-local-properties-approval',
+ 'uni-prop-local-approvals',
'ApprovalStateMachineArn'
),
statusFilter: 'SUCCEEDED',
@@ -144,7 +144,7 @@ describe('Tests that failed workflow', () => {
// Assert
const listExecutionsCommand = new ListExecutionsCommand({
stateMachineArn: await findOutputValue(
- 'uni-prop-local-properties-approval',
+ 'uni-prop-local-approvals',
'ApprovalStateMachineArn'
),
statusFilter: 'SUCCEEDED',
diff --git a/unicorn_properties/tests/integration/contract_status_changed_event.test.ts b/unicorn_approvals/tests/integration/contract_status_changed_event.test.ts
similarity index 97%
rename from unicorn_properties/tests/integration/contract_status_changed_event.test.ts
rename to unicorn_approvals/tests/integration/contract_status_changed_event.test.ts
index 6bfdeab4..0d1da878 100644
--- a/unicorn_properties/tests/integration/contract_status_changed_event.test.ts
+++ b/unicorn_approvals/tests/integration/contract_status_changed_event.test.ts
@@ -34,7 +34,7 @@ describe('Testing draft contract event handling', () => {
region: process.env.AWS_DEFAULT_REGION,
});
const contractStatusTableName = await findOutputValue(
- 'uni-prop-local-properties',
+ 'uni-prop-local-approvals',
'ContractStatusTableName'
);
@@ -64,7 +64,7 @@ describe('Testing draft contract event handling', () => {
region: process.env.AWS_DEFAULT_REGION,
});
const contractStatusTableName = await findOutputValue(
- 'uni-prop-local-properties',
+ 'uni-prop-local-approvals',
'ContractStatusTableName'
);
@@ -82,4 +82,4 @@ describe('Testing draft contract event handling', () => {
if (!ddbResp.Item) throw new Error('Contract not found');
expect(ddbResp.Item.contract_status?.S).toBe('APPROVED');
}, 30000);
-});
+});
\ No newline at end of file
diff --git a/unicorn_properties/tests/integration/helper.ts b/unicorn_approvals/tests/integration/helper.ts
similarity index 77%
rename from unicorn_properties/tests/integration/helper.ts
rename to unicorn_approvals/tests/integration/helper.ts
index 7ead4e80..66f79f45 100644
--- a/unicorn_properties/tests/integration/helper.ts
+++ b/unicorn_approvals/tests/integration/helper.ts
@@ -4,7 +4,6 @@ import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
import {
CloudFormationClient,
DescribeStacksCommand,
- DescribeStacksCommandOutput,
} from '@aws-sdk/client-cloudformation';
import {
BatchWriteCommand,
@@ -25,18 +24,19 @@ export const sleep = async (ms: number) =>
export async function* getCloudWatchLogsValues(
propertyId: string
): AsyncGenerator {
- const groupName = await findOutputValue(
- 'uni-prop-local-properties',
- 'UnicornPropertiesCatchAllLogGroupName'
+ const groupArn = await findOutputValue(
+ 'uni-prop-local-approvals',
+ 'UnicornApprovalsCatchAllLogGroupArn'
);
// Initialize the CloudWatch Logs client
- const cwl = new CloudWatchLogs({ region: process.env.AWS_DEFAULT_REGION });
+ const region = process.env.AWS_DEFAULT_REGION || process.env.AWS_REGION || 'ap-southeast-2';
+ const cwl = new CloudWatchLogs({ region });
// Get the CW LogStream with the latest log messages
const streamResponse = await cwl.send(
new DescribeLogStreamsCommand({
- logGroupName: groupName,
+ logGroupIdentifier: groupArn,
orderBy: 'LastEventTime',
descending: true,
limit: 3,
@@ -52,7 +52,7 @@ export async function* getCloudWatchLogsValues(
latestLogStreamNames.map(async (name) => {
return await cwl.send(
new GetLogEventsCommand({
- logGroupName: groupName,
+ logGroupIdentifier: groupArn,
logStreamName: name,
})
);
@@ -141,29 +141,21 @@ export async function initializeDatabase() {
}
}
-export const findOutputValue = async (StackName: string, outputKey: string) => {
- const cloudformation = new CloudFormationClient({
- region: process.env.AWS_DEFAULT_REGION,
- });
- const stackResources: DescribeStacksCommandOutput = await cloudformation.send(
+export const findOutputValue = async (StackName: string, outputKey: string): Promise => {
+ const region = process.env.AWS_DEFAULT_REGION || process.env.AWS_REGION || 'ap-southeast-2';
+ const cloudformation = new CloudFormationClient({ region });
+
+ const stackResources = await cloudformation.send(
new DescribeStacksCommand({ StackName })
);
- if (stackResources.Stacks === undefined || stackResources.Stacks?.length < 1)
- throw new Error(`Could not find stack resources named: ${StackName}`);
-
- if (
- stackResources.Stacks[0].Outputs === undefined ||
- stackResources.Stacks[0].Outputs?.length < 1
- ) {
- throw new Error(
- `Could not find stack outputs for stack named: ${StackName}`
- );
- }
-
- const outputValue = stackResources.Stacks[0].Outputs.find(
+
+ const output = stackResources.Stacks?.[0]?.Outputs?.find(
(output) => output.OutputKey === outputKey
- )?.OutputValue;
- if (outputValue === undefined)
- throw new Error(`Could not find stack output named: ${outputKey}`);
- return outputValue;
+ );
+
+ if (!output?.OutputValue) {
+ throw new Error(`Could not find output ${outputKey} in stack ${StackName}`);
+ }
+
+ return output.OutputValue;
};
diff --git a/unicorn_properties/tests/unit/contractStatusChangedEventHandler.test.ts b/unicorn_approvals/tests/unit/contractStatusChangedEventHandler.test.ts
similarity index 93%
rename from unicorn_properties/tests/unit/contractStatusChangedEventHandler.test.ts
rename to unicorn_approvals/tests/unit/contractStatusChangedEventHandler.test.ts
index af34fb16..e3b53e02 100644
--- a/unicorn_properties/tests/unit/contractStatusChangedEventHandler.test.ts
+++ b/unicorn_approvals/tests/unit/contractStatusChangedEventHandler.test.ts
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT-0
import { Context, EventBridgeEvent } from 'aws-lambda';
import { randomUUID } from 'crypto';
-import { lambdaHandler } from '../../src/properties_service/contractStatusChangedEventHandler';
+import { lambdaHandler } from '../../src/approvals_service/contractStatusChangedEventHandler';
import { mockClient } from 'aws-sdk-client-mock';
import {
DynamoDBClient,
@@ -48,7 +48,7 @@ describe('Unit tests for contract creation', function () {
version: '0',
time: 'nulltime',
region: 'ap-southeast-2',
- source: 'unicorn.properties',
+ source: 'unicorn.approvals',
resources: [''],
detail: {
contract_id: 'contract1',
diff --git a/unicorn_properties/tests/unit/propertiesApprovalSyncFunction.test.ts b/unicorn_approvals/tests/unit/propertiesApprovalSyncFunction.test.ts
similarity index 98%
rename from unicorn_properties/tests/unit/propertiesApprovalSyncFunction.test.ts
rename to unicorn_approvals/tests/unit/propertiesApprovalSyncFunction.test.ts
index 5458a154..4d2791ab 100644
--- a/unicorn_properties/tests/unit/propertiesApprovalSyncFunction.test.ts
+++ b/unicorn_approvals/tests/unit/propertiesApprovalSyncFunction.test.ts
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT-0
import { Context, DynamoDBBatchResponse } from 'aws-lambda';
import { randomUUID } from 'crypto';
-import { lambdaHandler } from '../../src/properties_service/propertiesApprovalSyncFunction';
+import { lambdaHandler } from '../../src/approvals_service/propertiesApprovalSyncFunction';
import { mockClient } from 'aws-sdk-client-mock';
import { SendTaskSuccessCommandInput, SFNClient } from '@aws-sdk/client-sfn';
diff --git a/unicorn_properties/tests/unit/waitForContractApprovalFunction.test.ts b/unicorn_approvals/tests/unit/waitForContractApprovalFunction.test.ts
similarity index 98%
rename from unicorn_properties/tests/unit/waitForContractApprovalFunction.test.ts
rename to unicorn_approvals/tests/unit/waitForContractApprovalFunction.test.ts
index e15ad96b..cfc15bb6 100644
--- a/unicorn_properties/tests/unit/waitForContractApprovalFunction.test.ts
+++ b/unicorn_approvals/tests/unit/waitForContractApprovalFunction.test.ts
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT-0
import { Context } from 'aws-lambda';
import { randomUUID } from 'crypto';
-import { lambdaHandler } from '../../src/properties_service/waitForContractApprovalFunction';
+import { lambdaHandler } from '../../src/approvals_service/waitForContractApprovalFunction';
import { mockClient } from 'aws-sdk-client-mock';
import {
DynamoDBClient,
diff --git a/unicorn_properties/tsconfig.json b/unicorn_approvals/tsconfig.json
similarity index 100%
rename from unicorn_properties/tsconfig.json
rename to unicorn_approvals/tsconfig.json
diff --git a/unicorn_contracts/Makefile b/unicorn_contracts/Makefile
index ba508c8b..41c8d6fd 100644
--- a/unicorn_contracts/Makefile
+++ b/unicorn_contracts/Makefile
@@ -1,9 +1,9 @@
#### Global Variables
-stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.yaml)
+stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.toml)
#### Build/Deploy Tasks
-ci: deps clean build deploy
+ci: deps build deploy
deps:
pnpm i
@@ -26,7 +26,7 @@ ddbPropertyId = $(call get_ddb_key,create_contract_valid_payload_1)
test: unit-test integration-test
unit-test:
-
+ pnpm test -- tests/unit
integration-test:
pnpm test -- tests/integration/
diff --git a/unicorn_contracts/README.md b/unicorn_contracts/README.md
index 1cfad3ba..61fdd998 100755
--- a/unicorn_contracts/README.md
+++ b/unicorn_contracts/README.md
@@ -4,13 +4,22 @@
## Architecture overview
-Unicorn Contract manages the contractual relationship between the customers and the Unicorn Properties agency. It's primary function is to allow Unicorn Properties agents to create a new contract for a property listing, and to have the contract approved once it's ready.
+The **Unicorn Contracts** service manages contractual relationships between customers and Unicorn Properties agency. The service handles standard terms and conditions, property service rates, fees, and additional services.
-The architecture is fairly straight forward. An API exposes the create contract and update contract methods. This information is recorded in a Amazon DynamoDB table which will contain all latest information about the contract and it's status.
+Each property can have only one active contract. Properties use their address as a unique identifier instead of a GUID, which correlates across services.
-Each time a new contract is created or updated, Unicorn Contracts publishes a `ContractStatusChanged` event to Amazon EventBridge signalling changes to the contract status. These events are consumed by **Unicorn Properties**, so it can track changes to contracts, without needing to take a direct dependency on Unicorn Contracts and it's database.
+For example: `usa/anytown/main-street/111`.
-Here is an example of an event that is published to EventBridge:
+The contract workflow operates as follows:
+
+1. Agents submit contract creation/update commands through the Contracts API
+1. The API sends requests to Amazon SQS
+1. A Contracts function processes the queue messages and updates Amazon DynamoDB
+1. DynamoDB Streams captures contract changes
+1. Amazon EventBridge Pipes transforms the DynamoDB records into ContractStatusChanged events
+1. Unicorn Approvals consumes these events to track contract changes without direct database dependencies
+
+An example of `ContractStatusChanged` event:
```json
{
diff --git a/unicorn_contracts/template.yaml b/unicorn_contracts/template.yaml
index 4b0db4c9..9bb5278a 100644
--- a/unicorn_contracts/template.yaml
+++ b/unicorn_contracts/template.yaml
@@ -15,8 +15,6 @@ Metadata:
- WS2001 # Rule disabled because check does not support !ToJsonString transform
- ES1001 # Rule disabled because our Lambda functions don't need DestinationConfig.OnFailure
- W3002 # Rule disabled as nested templates are being packaged
- - E3030 # Rule disabled due to using cfn-lint-serverless rules v0.3
- - E3002 # Rule disabled due to using cfn-lint-serverless rules v0.3
Parameters:
Stage:
@@ -45,11 +43,10 @@ Conditions:
Globals:
Api:
OpenApiVersion: 3.0.1
- TracingEnabled: true
Function:
Runtime: nodejs22.x
MemorySize: 512
- Timeout: 15
+ Timeout: 15
Tracing: Active
Architectures:
- x86_64
@@ -302,7 +299,7 @@ Resources:
- !Ref AWS::AccountId
source:
- "{{resolve:ssm:/uni-prop/UnicornContractsNamespace}}"
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- "{{resolve:ssm:/uni-prop/UnicornWebNamespace}}"
State: ENABLED #You may want to disable this rule in production
Targets:
diff --git a/unicorn_properties/README.md b/unicorn_properties/README.md
deleted file mode 100644
index 158150e0..00000000
--- a/unicorn_properties/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Developing Unicorn Properties
-
-
-
-## Architecture overview
-
-Unicorn Properties is primarily responsible for approving property listings for Unicorn Web.
-
-A core component of Unicorn Properties is the approvals workflow. The approvals workflow is implemented using an AWS Step Functions state machine. At a high level, the workflow will:
-
-* Check whether or not it has any contract information for the property it needs to approve. If there is no contract information, the approval process cannot be completed.
-* Ensure the sentiment of the property description is positive and that there no unsafe images. All checks must pass for the listing to be made public.
-* Ensure that the contract is in an APPROVED state before it can approve the listing. This accounts for a situation where the property listings are created before the contract has been signed and the services for Unicorn Properties are paid for.
-* Publish the result of the workflow via the `PublicationEvaluationCompleted` event.
-
-The workflow is initiated by a request made by an Unicorn Properties **agent** to have the property approved for publication. Once they have created a property listing (added property details and photos), they initiate the request in Unicorn Web, which generates a `PublicationApprovalRequested` event. This event contains the property information which the workflow processes.
-
-In order process the approvals workflow successfully, the properties service needs to know the current status of a contract. To remain fully decoupled from the **Contracts Service**, it maintains a local copy of contract status by consuming the `ContractStatusChanged` event. This is eliminates the need for the Contracts service to expose an API that gives other services access to its database, and allows the Properties service to function autonomously.
-
-When the workflow is paused to check to see whether or not the contract is in an approved state, the `WaitForContractApproval` state will update a contract status for a specified property with its task token. This initiates a stream event on the DynamoDB table. The Property approvals sync function handles DynamoDB stream events. It determines whether or not to pass AWS Step Function task token back to the state machine based on the contract state.
-
-If workflow is completed successfully, it will emit a `PublicationEvaluationCompleted` event, with an evaluation result of `APPROVED` or `DECLINED`. This is what the Property Web will listen to in order to make the list available for publication.
-
-## Note:
-
-Upon deleting the CloudFormation stack for this service, check if the `ApprovalStateMachine` StepFunction doesn't have any executions in `RUNNING` state. If there are, cancel those execution prior to deleting the CloudFormation stack.
diff --git a/unicorn_shared/Makefile b/unicorn_shared/Makefile
index ffc3833d..53074ee5 100644
--- a/unicorn_shared/Makefile
+++ b/unicorn_shared/Makefile
@@ -32,3 +32,6 @@ delete-images: ## Deletes all shared images stacks
--stack-name "uni-prop-$$env-images"; \
fi; \
done
+
+list-parameters: ## Lists all parameters in the Unicorn Properties namespace
+ aws ssm get-parameters-by-path --path "/uni-prop" --recursive --with-decryption --query 'Parameters[*].[Name,Value,Type]' --output table
\ No newline at end of file
diff --git a/unicorn_shared/uni-prop-namespaces.yaml b/unicorn_shared/uni-prop-namespaces.yaml
index 55602fb7..7df02f4c 100644
--- a/unicorn_shared/uni-prop-namespaces.yaml
+++ b/unicorn_shared/uni-prop-namespaces.yaml
@@ -14,12 +14,12 @@ Resources:
Name: !Sub /uni-prop/UnicornContractsNamespace
Value: "unicorn.contracts"
- UnicornPropertiesNamespaceParam:
+ UnicornApprovalsNamespaceParam:
Type: AWS::SSM::Parameter
Properties:
Type: String
- Name: !Sub /uni-prop/UnicornPropertiesNamespace
- Value: "unicorn.properties"
+ Name: !Sub /uni-prop/UnicornApprovalsNamespace
+ Value: "unicorn.approvals"
UnicornWebNamespaceParam:
Type: AWS::SSM::Parameter
@@ -35,9 +35,9 @@ Outputs:
Description: Unicorn Contracts namespace parameter
Value: !Ref UnicornContractsNamespaceParam
- UnicornPropertiesNamespace:
+ UnicornApprovalsNamespace:
Description: Unicorn Properties namespace parameter
- Value: !Ref UnicornPropertiesNamespaceParam
+ Value: !Ref UnicornApprovalsNamespaceParam
UnicornWebNamespace:
Description: Unicorn Web namespace parameter
@@ -49,7 +49,7 @@ Outputs:
UnicornPropertiesNamespaceValue:
Description: Unicorn Properties namespace parameter value
- Value: !GetAtt UnicornPropertiesNamespaceParam.Value
+ Value: !GetAtt UnicornApprovalsNamespaceParam.Value
UnicornWebNamespaceValue:
Description: Unicorn Web namespace parameter value
diff --git a/unicorn_web/Makefile b/unicorn_web/Makefile
index f986a2d9..e51bf48a 100644
--- a/unicorn_web/Makefile
+++ b/unicorn_web/Makefile
@@ -1,9 +1,9 @@
#### Global Variables
-stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.yaml)
+stackName := $(shell yq -oy '.default.global.parameters.stack_name' samconfig.toml)
#### Build/Deploy Tasks
-ci: deps clean build deploy
+ci: deps build deploy
deps:
pnpm i
diff --git a/unicorn_web/README.md b/unicorn_web/README.md
index 9e702539..38e17ea6 100644
--- a/unicorn_web/README.md
+++ b/unicorn_web/README.md
@@ -4,18 +4,15 @@
## Architecture Overview
-Unicorn Web is primarily responsible for allowing customers to search and view property listings. It also supports ability for agents to request approval for specific property. Those approval requests are sent to Property service for validation, before Properties table is updated with approval evaluation results.
+Unicorn Web lets customers search for and view property listings. The Web API also allows Unicorn Properties agents to request approval for specific properties that they want to publish so they may be returned in customer searches results. These requests are sent to the Unicorn Approvals service for validation.
-A core component of Unicorn Web are the Lambda functions which are responsible with completing API Gateway requests to:
+Lambda functions handle API Gateway requests to:
-- search approved property listings
-This function interacts with DynamoDB table to retrieve property listings marked as `APPROVED`. The API Gateway implementation and lambda code support multiple types of search patterns, and allow searching by city, street, or house number.
+- Search approved property listings: The **Search function** retrieves property listings marked as APPROVED from the DynamoDB table using multiple search patterns.
-- request approval of property listing
-This function sends an event to EventBridge requesting an approval for a property listing specified in the payload sent from client
+- Request property listing approval: The **Request Approval function** sends an EventBridge event requesting approval for a property listing specified in the payload.
-- publication approved function
-There is also a lambda function responsible for receiving any "Approval Evaluation Completed" events from EventBridge. This function writes the evaluation result to DynamoDB table.
+- Process approved listings: The **Publication Evaluation Event Handler function** processes `PublicationEvaluationCompleted` events from the Unicorn Approvals service and writes the evaluation result to the DynamoDB table.
### Testing the APIs
@@ -24,10 +21,10 @@ export API=`aws cloudformation describe-stacks --stack-name uni-prop-local-web -
curl --location --request POST "${API}request_approval" \
--header 'Content-Type: application/json' \
---data-raw '{"property_id": "usa/anytown/main-street/111"}'
+--data-raw '{"PropertyId": "usa/anytown/main-street/111"}'
curl -X POST ${API_URL}request_approval \
-H 'Content-Type: application/json' \
- -d '{"property_id":"usa/anytown/main-street/111"}' | jq
+ -d '{"PropertyId":"usa/anytown/main-street/111"}' | jq
```
diff --git a/unicorn_web/integration/subscriptions.yaml b/unicorn_web/integration/subscriptions.yaml
index d455cea4..fc27711f 100644
--- a/unicorn_web/integration/subscriptions.yaml
+++ b/unicorn_web/integration/subscriptions.yaml
@@ -20,10 +20,10 @@ Resources:
Name: unicorn.web-PublicationEvaluationCompleted
Description: PublicationEvaluationCompleted subscription
EventBusName:
- Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornPropertiesEventBusArn}}"
+ Fn::Sub: "{{resolve:ssm:/uni-prop/${Stage}/UnicornApprovalsEventBusArn}}"
EventPattern:
source:
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
detail-type:
- PublicationEvaluationCompleted
State: ENABLED
diff --git a/unicorn_web/src/approvals_service/powertools.ts b/unicorn_web/src/publication_manager_service/powertools.ts
similarity index 100%
rename from unicorn_web/src/approvals_service/powertools.ts
rename to unicorn_web/src/publication_manager_service/powertools.ts
diff --git a/unicorn_web/src/approvals_service/publicationApprovedEventHandler.ts b/unicorn_web/src/publication_manager_service/publicationApprovedEventHandler.ts
similarity index 95%
rename from unicorn_web/src/approvals_service/publicationApprovedEventHandler.ts
rename to unicorn_web/src/publication_manager_service/publicationApprovedEventHandler.ts
index 4a8170c9..9542123c 100644
--- a/unicorn_web/src/approvals_service/publicationApprovedEventHandler.ts
+++ b/unicorn_web/src/publication_manager_service/publicationApprovedEventHandler.ts
@@ -9,8 +9,8 @@ import {
UpdateItemCommand,
UpdateItemCommandInput,
} from '@aws-sdk/client-dynamodb';
-import { PublicationEvaluationCompleted } from '../schema/unicorn_properties/publicationevaluationcompleted/PublicationEvaluationCompleted';
-import { Marshaller } from '../schema/unicorn_properties/publicationevaluationcompleted/marshaller/Marshaller';
+import { PublicationEvaluationCompleted } from '../schema/unicorn_approvals/publicationevaluationcompleted/PublicationEvaluationCompleted';
+import { Marshaller } from '../schema/unicorn_approvals/publicationevaluationcompleted/marshaller/Marshaller';
// Empty configuration for DynamoDB
const ddbClient = new DynamoDBClient({});
diff --git a/unicorn_web/src/approvals_service/requestApprovalFunction.ts b/unicorn_web/src/publication_manager_service/requestApprovalFunction.ts
similarity index 100%
rename from unicorn_web/src/approvals_service/requestApprovalFunction.ts
rename to unicorn_web/src/publication_manager_service/requestApprovalFunction.ts
diff --git a/unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/AWSEvent.ts b/unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/AWSEvent.ts
similarity index 100%
rename from unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/AWSEvent.ts
rename to unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/AWSEvent.ts
diff --git a/unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/PublicationEvaluationCompleted.ts b/unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/PublicationEvaluationCompleted.ts
similarity index 100%
rename from unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/PublicationEvaluationCompleted.ts
rename to unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/PublicationEvaluationCompleted.ts
diff --git a/unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/marshaller/Marshaller.ts b/unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/marshaller/Marshaller.ts
similarity index 100%
rename from unicorn_web/src/schema/unicorn_properties/publicationevaluationcompleted/marshaller/Marshaller.ts
rename to unicorn_web/src/schema/unicorn_approvals/publicationevaluationcompleted/marshaller/Marshaller.ts
diff --git a/unicorn_web/template.yaml b/unicorn_web/template.yaml
index ed2285ff..70cf47d1 100644
--- a/unicorn_web/template.yaml
+++ b/unicorn_web/template.yaml
@@ -15,8 +15,6 @@ Metadata:
- WS2001 # Rule disabled because check does not support !ToJsonString transform
- ES1001 # Rule disabled because our Lambda functions don't need DestinationConfig.OnFailure
- W3002 # Rule disabled as nested templates are being packaged
- - W3002 # Rule disabled as nested templates are being packaged
- - E3030 # Rule disabled due to using cfn-lint-serverless rules v0.3
Parameters:
Stage:
@@ -118,7 +116,7 @@ Resources:
RequestApprovalFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: src/approvals_service
+ CodeUri: src/publication_manager_service
Handler: requestApprovalFunction.lambdaHandler
Policies:
- EventBridgePutEventsPolicy:
@@ -156,7 +154,7 @@ Resources:
PublicationApprovedEventHandlerFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: src/approvals_service
+ CodeUri: src/publication_manager_service
Handler: publicationApprovedEventHandler.lambdaHandler
Policies:
- DynamoDBCrudPolicy:
@@ -173,7 +171,7 @@ Resources:
EventBusName: !Ref UnicornWebEventBus
Pattern:
source:
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
detail-type:
- PublicationEvaluationCompleted
Metadata: # Manage esbuild properties
@@ -386,7 +384,7 @@ Resources:
- !Ref AWS::AccountId
source:
- "{{resolve:ssm:/uni-prop/UnicornContractsNamespace}}"
- - "{{resolve:ssm:/uni-prop/UnicornPropertiesNamespace}}"
+ - "{{resolve:ssm:/uni-prop/UnicornApprovalsNamespace}}"
- "{{resolve:ssm:/uni-prop/UnicornWebNamespace}}"
State: ENABLED #You may want to disable this rule in production
Targets:
@@ -474,7 +472,7 @@ Outputs:
BaseUrl:
Description: Web service API endpoint
Value: !Sub "https://${UnicornWebApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}"
- UnicornWebRestApiUrl:
+ UnicornWebApiUrl:
Description: Web service API endpoint
Value: !Sub "https://${UnicornWebApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${Stage}/"
@@ -486,7 +484,7 @@ Outputs:
Description: "GET request to list all properties in a given street"
Value: !Sub "https://${UnicornWebApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${Stage}/search/{country}/{city}/{street}"
ApiPropertyApproval:
- Description: "POST request to add a property to the database"
+ Description: "POST request approval to allow property to be searchable"
Value: !Sub "https://${UnicornWebApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${Stage}/request_approval"
ApiPropertyDetails:
Description: "GET request to get the full details of a single property"
diff --git a/unicorn_web/tests/events/eventbridge/put_event_publication_evaluation_completed.json b/unicorn_web/tests/events/eventbridge/put_event_publication_evaluation_completed.json
index 6b715f68..25e8b56c 100644
--- a/unicorn_web/tests/events/eventbridge/put_event_publication_evaluation_completed.json
+++ b/unicorn_web/tests/events/eventbridge/put_event_publication_evaluation_completed.json
@@ -1,6 +1,6 @@
[
{
- "Source": "unicorn.properties",
+ "Source": "unicorn.approvals",
"Detail": "{\"property_id\":\"usa/anytown/main-street/111\",\"evaluation_result\": \"APPROVED\"}",
"DetailType": "PublicationEvaluationCompleted",
"EventBusName": "UnicornWebBus-local"