Skip to content

Commit

Permalink
Use LocalStack for local testing.
Browse files Browse the repository at this point in the history
  • Loading branch information
gogarufi committed Oct 8, 2024
1 parent 5577f48 commit 72a3f65
Show file tree
Hide file tree
Showing 17 changed files with 741 additions and 265 deletions.
41 changes: 25 additions & 16 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,36 @@ DATABASE_SCHEMA=public
DATABASE_SSL_SELF=false
PUBLIC_FRONTEND_URL="http://localhost:5173" # Used for emails linking to the frontend

# AWS SES Settings
AWS_ACCESS_KEY_ID="EXAMPLE_KEY"
AWS_SECRET_ACCESS_KEY="EXAMPLE_SECRET"
AWS_REGION="eu-north-1"
## AWS LocalStack development endpoint
LOCALSTACK_ENDPOINT=http://127.0.0.1:4566

## AWS SES Settings

## These settings correspond to LocalStack system defaults
## https://docs.localstack.cloud/references/configuration/
AWS_ACCESS_KEY_ID="test"
AWS_SECRET_ACCESS_KEY="test"
AWS_REGION=us-east-1

# `MAIL_FROM` and `MAIL_REPLY_TO` variables will not take effect for emails sent by `user-permissions` Strapi plugin
# (f.e. reset password emails) as they are configured separately via Strapi UI in `Settings > Email Templates`.
MAIL_FROM="OpenVAA Voting Advice Application <[email protected]>"
MAIL_REPLY_TO="OpenVAA Admin <[email protected]>"
MAIL_FROM="OpenVAA Voting Advice Application <[email protected]>"
MAIL_REPLY_TO="OpenVAA Admin <[email protected]>"

## AWS S3 settings

# Maildev settings (used only in dev)
MAILDEV_PORT=1080
AWS_S3_BUCKET=static.example.com

## AWS S3 settings for static content storage
AWS_S3_ACCESS_KEY_ID="EXAMPLE_KEY"
AWS_S3_ACCESS_SECRET="EXAMPLE_SECRET"
AWS_S3_REGION=eu-north-1
AWS_S3_BUCKET=static-example-com
## These settings correspond to LocalStack system defaults
## https://docs.localstack.cloud/references/configuration/
AWS_S3_ACCESS_KEY_ID="test"
AWS_S3_ACCESS_SECRET="test"
AWS_S3_REGION=us-east-1

## Will be used as the base URL for media content uploaded via Strapi's UI.
## Requires an existing CNAME DNS record for the corresponding subdomain which points to AWS S3 bucket where the content is stored.
STATIC_CONTENT_BASE_URL=https://static.example.com
## The base URL is used to access static content uploaded via Strapi's UI to AWS S3:
## - on production it uses a dedicated subdomain which is linked to an eponymous AWS S3 bucket via a CNAME DNS record
## - in development it points directly to LocalStack host and is appended by the S3 bucket name in Strapi's `plugin.ts`
STATIC_CONTENT_BASE_URL=http://localhost:4566
STATIC_MEDIA_CONTENT_PATH=public/media

# Point to a folder (relative to /backend/vaa-strapi) if you want to load data on initialise. This will only take place if the database contains no Election
Expand Down
35 changes: 24 additions & 11 deletions backend/vaa-strapi/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,34 @@ PUBLIC_FRONTEND_URL="http://localhost:5173" # Used for emails linking to the fro
GENERATE_MOCK_DATA_ON_INITIALISE=true # Set to true to enable mock data on an empty database
GENERATE_MOCK_DATA_ON_RESTART=false # Used only in development builds

AWS_ACCESS_KEY_ID="EXAMPLE_KEY"
AWS_SECRET_ACCESS_KEY="EXAMPLE_SECRET"
AWS_REGION="eu-north-1"
## AWS LocalStack development endpoint
LOCALSTACK_ENDPOINT=http://127.0.0.1:4566

## AWS SES Settings

## These settings correspond to LocalStack system defaults
## https://docs.localstack.cloud/references/configuration/
AWS_ACCESS_KEY_ID="test"
AWS_SECRET_ACCESS_KEY="test"
AWS_REGION=us-east-1

# `MAIL_FROM` and `MAIL_REPLY_TO` variables will not take effect for emails sent by `user-permissions` Strapi plugin
# (f.e. reset password emails) as they are configured separately via Strapi UI in `Settings > Email Templates`.
MAIL_FROM="OpenVAA Voting Advice Application <[email protected]>"
MAIL_REPLY_TO="OpenVAA Admin <[email protected]>"

## AWS S3 settings for static content storage
AWS_S3_ACCESS_KEY_ID="EXAMPLE_KEY"
AWS_S3_ACCESS_SECRET="EXAMPLE_SECRET"
AWS_S3_REGION=eu-north-1
AWS_S3_BUCKET=static-example-com
## AWS S3 settings

AWS_S3_BUCKET=static.example.com

## These settings correspond to LocalStack system defaults
## https://docs.localstack.cloud/references/configuration/
AWS_S3_ACCESS_KEY_ID="test"
AWS_S3_ACCESS_SECRET="test"
AWS_S3_REGION=us-east-1

## Will be used as the base URL for media content uploaded via Strapi's UI.
## Requires an existing CNAME DNS record for the corresponding subdomain which points to AWS S3 bucket where the content is stored.
STATIC_CONTENT_BASE_URL=https://static.example.com
## The base URL is used to access static content uploaded via Strapi's UI to AWS S3:
## - on production it uses a dedicated subdomain which is linked to an eponymous AWS S3 bucket via a CNAME DNS record
## - in development it points directly to LocalStack host and is appended by the S3 bucket name in Strapi's `plugin.ts`
STATIC_CONTENT_BASE_URL=http://localhost:4566
STATIC_MEDIA_CONTENT_PATH=public/media
21 changes: 0 additions & 21 deletions backend/vaa-strapi/config/env/development/plugins.ts

This file was deleted.

33 changes: 31 additions & 2 deletions backend/vaa-strapi/config/middlewares.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
module.exports = [
module.exports = ({env}) => [
'strapi::logger',
'strapi::errors',
'strapi::security',
/*
* To enable AWS S3 support:
* https://github.com/strapi/strapi/tree/main/packages/providers/upload-aws-s3
**/
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", env('NODE_ENV') === 'development' ? 'http:' : 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
`${env('STATIC_CONTENT_BASE_URL')}`
],
'media-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
`${env('STATIC_CONTENT_BASE_URL')}`
],
upgradeInsecureRequests: null
}
}
}
},
'strapi::cors',
'strapi::poweredBy',
'strapi::query',
Expand Down
58 changes: 33 additions & 25 deletions backend/vaa-strapi/config/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,8 @@
const aws = require('@aws-sdk/client-ses');

export default ({env}) => {
/**
* Strapi initilises nodemailer transporter only once using main plugin config.
* It allows to override only transporter specific (SMPT or SES) settings using [env]/plugins.ts, not the transporter type itself.
* So we have to make sure that for development we initilise the transporter as SMTP to be able to use maildev.
*/
const emailProviderOptions =
env('NODE_ENV') === 'development'
? undefined
: {
SES: {
ses: new aws.SES({
apiVersion: '2010-12-01',
region: env('AWS_REGION'),
credentials: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_SECRET_ACCESS_KEY')
}
}),
aws
},
// max 14 messages per second to comply with AWS SES
sendingRate: 14
};
const isDev = env('NODE_ENV') === 'development';

return {
'users-permissions': {
config: {
Expand All @@ -39,7 +18,20 @@ export default ({env}) => {
config: {
provider: 'nodemailer',
providerOptions: {
...emailProviderOptions
SES: {
ses: new aws.SES({
endpoint: env('LOCALSTACK_ENDPOINT'),
apiVersion: '2010-12-01',
region: env('AWS_REGION'),
credentials: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_SECRET_ACCESS_KEY')
}
}),
aws
},
// max 14 messages per second to comply with AWS SES
sendingRate: 14
},
settings: {
defaultFrom: env('MAIL_FROM'),
Expand All @@ -51,9 +43,25 @@ export default ({env}) => {
config: {
provider: 'aws-s3',
providerOptions: {
baseUrl: env('STATIC_CONTENT_BASE_URL'),
/*
* The base URL on production uses a dedicated subdomain which is linked to AWS S3 bucket via CNAME DNS record.
**/
baseUrl: isDev
? `${env('STATIC_CONTENT_BASE_URL')}/${env('AWS_S3_BUCKET')}`
: env('STATIC_CONTENT_BASE_URL'),
rootPath: env('STATIC_MEDIA_CONTENT_PATH'),
s3Options: {
/*
* In development we use local AWS - LocalStack.
**/
endpoint: isDev ? env('LOCALSTACK_ENDPOINT') : undefined,
/*
* In development we want to use "Path" style S3 URLs, since
* Docker services run locally are unable to resolve "Virtual-Hosted" style S3 URLs.
* https://docs.localstack.cloud/user-guide/aws/s3/#path-style-and-virtual-hosted-style-requests
*
**/
forcePathStyle: isDev,
credentials: {
accessKeyId: env('AWS_S3_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_S3_ACCESS_SECRET')
Expand Down
26 changes: 26 additions & 0 deletions backend/vaa-strapi/docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
services:
# LocalStack configuration: https://docs.localstack.cloud/references/configuration/
awslocal:
image: localstack/localstack
ports:
- '127.0.0.1:4566:4566'
environment:
DEBUG: 1
AWS_REGION: ${AWS_REGION}
MAIL_FROM: ${MAIL_FROM}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_S3_ACCESS_KEY_ID: ${AWS_S3_ACCESS_KEY_ID}
AWS_S3_ACCESS_SECRET: ${AWS_S3_ACCESS_SECRET}
AWS_S3_REGION: ${AWS_S3_REGION}
AWS_S3_BUCKET: ${AWS_S3_BUCKET}
volumes:
- awslocal:/var/lib/localstack
- ./localstack-init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh
- ./localstack-s3-cors-policy.json:/etc/localstack/s3-cors-policy.json
# Mounting the Docker socket /var/run/docker.sock as a volume is required for some services
# that use Docker to provide the emulation, such as AWS Lambda.
- '/var/run/docker.sock:/var/run/docker.sock'
strapi:
build:
# Context includes the root of the repository so that we can expose shared/ module.
Expand All @@ -7,6 +29,8 @@ services:
target: development
ports:
- ${STRAPI_PORT}:${STRAPI_PORT}
depends_on:
- 'awslocal'
restart: always
environment:
STRAPI_HOST: ${STRAPI_HOST}
Expand Down Expand Up @@ -36,6 +60,7 @@ services:
AWS_S3_BUCKET: ${AWS_S3_BUCKET}
STATIC_CONTENT_BASE_URL: ${STATIC_CONTENT_BASE_URL}
STATIC_MEDIA_CONTENT_PATH: ${STATIC_MEDIA_CONTENT_PATH}
LOCALSTACK_ENDPOINT: http://awslocal:4566
volumes:
# Creating this volume will make Docker update changes from local automatically
# Note that this only applies to src/, where all the source code is anyway.
Expand Down Expand Up @@ -68,3 +93,4 @@ services:
volumes:
postgres:
strapi-uploads:
awslocal:
6 changes: 6 additions & 0 deletions backend/vaa-strapi/localstack-init-aws.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
AWS_ACCESS_KEY_ID=$AWS_S3_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_S3_ACCESS_SECRET awslocal s3api create-bucket --bucket $AWS_S3_BUCKET --region $AWS_S3_REGION

AWS_ACCESS_KEY_ID=$AWS_S3_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_S3_ACCESS_SECRET awslocal s3api put-bucket-cors --bucket $AWS_S3_BUCKET --region $AWS_S3_REGION --cors-configuration file:///etc/localstack/s3-cors-policy.json

AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY awslocal ses verify-email-identity --email-address $MAIL_FROM --region $AWS_REGION
11 changes: 11 additions & 0 deletions backend/vaa-strapi/localstack-s3-cors-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"CORSRules": [
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["*"],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
}
2 changes: 1 addition & 1 deletion backend/vaa-strapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@strapi/plugin-documentation": "^4.25.1",
"@strapi/plugin-i18n": "^4.25.1",
"@strapi/plugin-users-permissions": "^4.25.1",
"@strapi/provider-email-nodemailer": "^4.25.1",
"@strapi/provider-email-nodemailer": "^5.0.2",
"@strapi/provider-upload-aws-s3": "^5.0.1",
"@strapi/strapi": "^4.25.1",
"pg": "^8.12.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"x-generation-date": "2024-09-10T08:41:53.329Z"
"x-generation-date": "2024-10-08T22:09:53.144Z"
},
"x-strapi-config": {
"path": "/documentation",
Expand Down
Loading

0 comments on commit 72a3f65

Please sign in to comment.