mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
refator(api): drop useless SES SDK (#65496)
This commit is contained in:
committed by
GitHub
parent
1fb20ded39
commit
7b8273e0e0
@@ -4,7 +4,6 @@
|
|||||||
"url": "https://github.com/freeCodeCamp/freeCodeCamp/issues"
|
"url": "https://github.com/freeCodeCamp/freeCodeCamp/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-ses": "3.1019.0",
|
|
||||||
"@fastify/accepts": "5.0.4",
|
"@fastify/accepts": "5.0.4",
|
||||||
"@fastify/cookie": "11.0.2",
|
"@fastify/cookie": "11.0.2",
|
||||||
"@fastify/csrf-protection": "7.1.0",
|
"@fastify/csrf-protection": "7.1.0",
|
||||||
|
|||||||
+2
-6
@@ -18,8 +18,7 @@ import addFormats from 'ajv-formats';
|
|||||||
import prismaPlugin from './db/prisma.js';
|
import prismaPlugin from './db/prisma.js';
|
||||||
import cookies from './plugins/cookies.js';
|
import cookies from './plugins/cookies.js';
|
||||||
import cors from './plugins/cors.js';
|
import cors from './plugins/cors.js';
|
||||||
import { NodemailerProvider } from './plugins/mail-providers/nodemailer.js';
|
import { createMailProvider } from './plugins/mail-providers/nodemailer.js';
|
||||||
import { SESProvider } from './plugins/mail-providers/ses.js';
|
|
||||||
import mailer from './plugins/mailer.js';
|
import mailer from './plugins/mailer.js';
|
||||||
import redirectWithMessage from './plugins/redirect-with-message.js';
|
import redirectWithMessage from './plugins/redirect-with-message.js';
|
||||||
import security from './plugins/security.js';
|
import security from './plugins/security.js';
|
||||||
@@ -36,7 +35,6 @@ import * as protectedRoutes from './routes/protected/index.js';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
API_LOCATION,
|
API_LOCATION,
|
||||||
EMAIL_PROVIDER,
|
|
||||||
FCC_ENABLE_DEV_LOGIN_MODE,
|
FCC_ENABLE_DEV_LOGIN_MODE,
|
||||||
FCC_ENABLE_SWAGGER_UI,
|
FCC_ENABLE_SWAGGER_UI,
|
||||||
FCC_ENABLE_SHADOW_CAPTURE,
|
FCC_ENABLE_SHADOW_CAPTURE,
|
||||||
@@ -135,9 +133,7 @@ export const build = async (
|
|||||||
clientKey: GROWTHBOOK_FASTIFY_CLIENT_KEY
|
clientKey: GROWTHBOOK_FASTIFY_CLIENT_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
const provider =
|
void fastify.register(mailer, { provider: createMailProvider() });
|
||||||
EMAIL_PROVIDER === 'ses' ? new SESProvider() : new NodemailerProvider();
|
|
||||||
void fastify.register(mailer, { provider });
|
|
||||||
|
|
||||||
// Swagger plugin
|
// Swagger plugin
|
||||||
if (FCC_ENABLE_SWAGGER_UI ?? fastify.gb.isOn('swagger-ui')) {
|
if (FCC_ENABLE_SWAGGER_UI ?? fastify.gb.isOn('swagger-ui')) {
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
import nodemailer, { Transporter } from 'nodemailer';
|
import nodemailer, { Transporter } from 'nodemailer';
|
||||||
|
|
||||||
import { MailProvider, SendEmailArgs } from '../mailer.js';
|
import { MailProvider, SendEmailArgs } from '../mailer.js';
|
||||||
import { MAILPIT_HOST } from '../../utils/env.js';
|
import {
|
||||||
|
EMAIL_PROVIDER,
|
||||||
|
MAILPIT_HOST,
|
||||||
|
SES_SMTP_HOST,
|
||||||
|
SES_SMTP_USERNAME,
|
||||||
|
SES_SMTP_PASSWORD
|
||||||
|
} from '../../utils/env.js';
|
||||||
|
|
||||||
|
export type NodemailerConfig = {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
secure: boolean;
|
||||||
|
auth: { user: string; pass: string };
|
||||||
|
tls?: { rejectUnauthorized: boolean };
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodemailerProvider is a wrapper around nodemailer that provides a clean
|
* NodemailerProvider is a wrapper around nodemailer that provides a clean
|
||||||
@@ -11,22 +25,12 @@ export class NodemailerProvider implements MailProvider {
|
|||||||
private transporter: Transporter;
|
private transporter: Transporter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up nodemailer, with hardcoded configuration. This is intended for
|
* Sets up nodemailer with the provided configuration.
|
||||||
* use in development with Mailpit.
|
*
|
||||||
|
* @param config - The nodemailer transport configuration.
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(config: NodemailerConfig) {
|
||||||
this.transporter = nodemailer.createTransport({
|
this.transporter = nodemailer.createTransport(config);
|
||||||
host: MAILPIT_HOST,
|
|
||||||
secure: false,
|
|
||||||
port: 1025,
|
|
||||||
auth: {
|
|
||||||
user: 'test',
|
|
||||||
pass: 'test'
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
rejectUnauthorized: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,3 +53,26 @@ export class NodemailerProvider implements MailProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a mail provider based on the EMAIL_PROVIDER environment variable.
|
||||||
|
*/
|
||||||
|
export function createMailProvider(): NodemailerProvider {
|
||||||
|
return EMAIL_PROVIDER === 'ses'
|
||||||
|
? new NodemailerProvider({
|
||||||
|
host: SES_SMTP_HOST,
|
||||||
|
port: 465,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: SES_SMTP_USERNAME ?? '',
|
||||||
|
pass: SES_SMTP_PASSWORD ?? ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: new NodemailerProvider({
|
||||||
|
host: MAILPIT_HOST,
|
||||||
|
port: 1025,
|
||||||
|
secure: false,
|
||||||
|
auth: { user: 'test', pass: 'test' },
|
||||||
|
tls: { rejectUnauthorized: false }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
import {
|
|
||||||
SESClient,
|
|
||||||
SESClientConfig,
|
|
||||||
SendEmailCommand
|
|
||||||
} from '@aws-sdk/client-ses';
|
|
||||||
|
|
||||||
import { MailProvider, SendEmailArgs } from '../mailer.js';
|
|
||||||
import { SES_ID, SES_SECRET, SES_REGION } from '../../utils/env.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SESProvider is a wrapper around nodemailer that provides a clean interface
|
|
||||||
* for sending email.
|
|
||||||
*/
|
|
||||||
export class SESProvider implements MailProvider {
|
|
||||||
private client: SESClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up SESClient and configures it with keys pulled from environment.
|
|
||||||
*/
|
|
||||||
constructor() {
|
|
||||||
if (!SES_ID || !SES_SECRET || !SES_REGION) {
|
|
||||||
throw new Error('Email service is set to SES but missing required keys.');
|
|
||||||
}
|
|
||||||
const awsConfig: SESClientConfig = {
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: SES_ID,
|
|
||||||
secretAccessKey: SES_SECRET
|
|
||||||
},
|
|
||||||
region: SES_REGION
|
|
||||||
};
|
|
||||||
this.client = new SESClient(awsConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends an email using the SES sdk.
|
|
||||||
*
|
|
||||||
* @param param Email options.
|
|
||||||
* @param param.to Email address to send to.
|
|
||||||
* @param param.from Email address to send from.
|
|
||||||
* @param param.subject Email subject.
|
|
||||||
* @param param.text Email body (raw text only).
|
|
||||||
* @param param.cc [Optional] Email address to CC.
|
|
||||||
*/
|
|
||||||
async send({ to, from, subject, text, cc }: SendEmailArgs) {
|
|
||||||
const opts = new SendEmailCommand({
|
|
||||||
Destination: {
|
|
||||||
ToAddresses: [to],
|
|
||||||
CcAddresses: cc ? [cc] : []
|
|
||||||
},
|
|
||||||
Message: {
|
|
||||||
Subject: {
|
|
||||||
Data: subject,
|
|
||||||
Charset: 'UTF-8'
|
|
||||||
},
|
|
||||||
Body: {
|
|
||||||
Text: {
|
|
||||||
Charset: 'UTF-8',
|
|
||||||
Data: text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Source: from
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.client.send(opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-8
@@ -94,12 +94,18 @@ assert.ok(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (process.env.FREECODECAMP_NODE_ENV !== 'development') {
|
if (process.env.FREECODECAMP_NODE_ENV !== 'development') {
|
||||||
assert.ok(process.env.SES_ID);
|
assert.ok(
|
||||||
assert.ok(process.env.SES_SECRET);
|
process.env.SES_SMTP_USERNAME,
|
||||||
|
'SES_SMTP_USERNAME is required in production.'
|
||||||
|
);
|
||||||
|
assert.ok(
|
||||||
|
process.env.SES_SMTP_PASSWORD,
|
||||||
|
'SES_SMTP_PASSWORD is required in production.'
|
||||||
|
);
|
||||||
assert.notEqual(
|
assert.notEqual(
|
||||||
process.env.SES_SECRET,
|
process.env.SES_SMTP_PASSWORD,
|
||||||
'ses_secret_from_aws',
|
'ses_smtp_password_from_aws',
|
||||||
'The SES secret should be changed from the default value.'
|
'The SES SMTP password should be changed from the default value.'
|
||||||
);
|
);
|
||||||
assert.ok(process.env.COOKIE_DOMAIN);
|
assert.ok(process.env.COOKIE_DOMAIN);
|
||||||
assert.notEqual(process.env.COOKIE_SECRET, 'a_cookie_secret');
|
assert.notEqual(process.env.COOKIE_SECRET, 'a_cookie_secret');
|
||||||
@@ -209,9 +215,10 @@ export const SENTRY_ENVIRONMENT =
|
|||||||
export const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN;
|
export const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN;
|
||||||
export const COOKIE_SECRET = process.env.COOKIE_SECRET;
|
export const COOKIE_SECRET = process.env.COOKIE_SECRET;
|
||||||
export const JWT_SECRET = process.env.JWT_SECRET;
|
export const JWT_SECRET = process.env.JWT_SECRET;
|
||||||
export const SES_ID = process.env.SES_ID;
|
export const SES_SMTP_USERNAME = process.env.SES_SMTP_USERNAME;
|
||||||
export const SES_SECRET = process.env.SES_SECRET;
|
export const SES_SMTP_PASSWORD = process.env.SES_SMTP_PASSWORD;
|
||||||
export const SES_REGION = process.env.SES_REGION || 'us-east-1';
|
export const SES_SMTP_HOST =
|
||||||
|
process.env.SES_SMTP_HOST || 'email-smtp.us-east-1.amazonaws.com';
|
||||||
export const SHOW_UPCOMING_CHANGES =
|
export const SHOW_UPCOMING_CHANGES =
|
||||||
process.env.SHOW_UPCOMING_CHANGES === 'true';
|
process.env.SHOW_UPCOMING_CHANGES === 'true';
|
||||||
export const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
|
export const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
|
||||||
|
|||||||
@@ -34,6 +34,9 @@
|
|||||||
"SES_ID",
|
"SES_ID",
|
||||||
"SES_REGION",
|
"SES_REGION",
|
||||||
"SES_SECRET",
|
"SES_SECRET",
|
||||||
|
"SES_SMTP_HOST",
|
||||||
|
"SES_SMTP_PASSWORD",
|
||||||
|
"SES_SMTP_USERNAME",
|
||||||
"SHOW_UPCOMING_CHANGES",
|
"SHOW_UPCOMING_CHANGES",
|
||||||
"SOCRATES_API_KEY",
|
"SOCRATES_API_KEY",
|
||||||
"SOCRATES_ENDPOINT",
|
"SOCRATES_ENDPOINT",
|
||||||
@@ -73,6 +76,9 @@
|
|||||||
"SES_ID",
|
"SES_ID",
|
||||||
"SES_REGION",
|
"SES_REGION",
|
||||||
"SES_SECRET",
|
"SES_SECRET",
|
||||||
|
"SES_SMTP_HOST",
|
||||||
|
"SES_SMTP_PASSWORD",
|
||||||
|
"SES_SMTP_USERNAME",
|
||||||
"SHOW_UPCOMING_CHANGES",
|
"SHOW_UPCOMING_CHANGES",
|
||||||
"SOCRATES_API_KEY",
|
"SOCRATES_API_KEY",
|
||||||
"SOCRATES_ENDPOINT",
|
"SOCRATES_ENDPOINT",
|
||||||
|
|||||||
Generated
+17
-886
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -70,13 +70,13 @@ FCC_API_LOG_LEVEL=info
|
|||||||
FCC_API_LOG_TRANSPORT=pretty
|
FCC_API_LOG_TRANSPORT=pretty
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
# use ses in production
|
# use ses in production, nodemailer for local development (with Mailpit)
|
||||||
EMAIL_PROVIDER=nodemailer
|
EMAIL_PROVIDER=nodemailer
|
||||||
# SES_ID needs to be empty for now, since the api-server will use SES in testing
|
# SES SMTP credentials (required in production)
|
||||||
# if it is set.
|
# Generate these from AWS IAM: https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html
|
||||||
SES_ID=
|
SES_SMTP_USERNAME=
|
||||||
SES_SECRET=ses_secret_from_aws
|
SES_SMTP_PASSWORD=ses_smtp_password_from_aws
|
||||||
SES_REGION=us-east-1
|
SES_SMTP_HOST=email-smtp.us-east-1.amazonaws.com
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
# Client
|
# Client
|
||||||
|
|||||||
Reference in New Issue
Block a user