Skip to content

Commit 402f2f6

Browse files
committed
feat: api status endpoint
1 parent 6672eba commit 402f2f6

File tree

8 files changed

+138
-102
lines changed

8 files changed

+138
-102
lines changed

.github/workflows/shared-build-and-deploy.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ jobs:
136136
containerRegistryUsername=${{ github.actor }} \
137137
containerRegistryPassword=${{ secrets.PACKAGES_TOKEN }} \
138138
branchName="$BRANCH_NAME" \
139+
gitSha="${{ needs.build.outputs.sha-short }}" \
139140
workspaceName='shared-log-analytics' \
140141
appInsightsName='shared-app-insights' \
141142
managedEnvironmentName='shared-env' \

infra/main.bicep

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ param containerRegistryUsername string
66
param containerRegistryPassword string
77

88
param branchName string
9+
param gitSha string
910

1011
param workspaceName string
1112
param appInsightsName string
@@ -141,6 +142,8 @@ resource webServiceContainerApp 'Microsoft.App/containerApps@2024-03-01' = {
141142
name: 'APPSETTINGS_PRAYER_REQUEST_RECIPIENT_EMAIL'
142143
value: APPSETTINGS_PRAYER_REQUEST_RECIPIENT_EMAIL
143144
}
145+
{ name: 'APPSETTINGS_BRANCH_NAME', value: branchName }
146+
{ name: 'APPSETTINGS_GIT_SHA', value: gitSha }
144147
]
145148
}
146149
]

src/server/src/config.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
21
export interface IConfig {
32
port: number;
43
prettyLog: boolean;
4+
apiKey: string;
5+
domain: string;
6+
prayerRequestFromEmail: string;
7+
prayerRequestRecipientEmail: string;
8+
branchName: string;
9+
gitSha: string;
510
}
611

7-
const config = {
8-
port: process.env.NODE_PORT || 3000,
12+
const config: IConfig = {
13+
port: process.env.NODE_PORT ? Number(process.env.NODE_PORT) : 3000,
914
prettyLog: process.env.NODE_ENV == 'development',
15+
apiKey: process.env.APPSETTINGS_API_KEY ?? 'unknown', // long guid from mailgun
16+
domain: process.env.APPSETTINGS_DOMAIN ?? 'unknown', // eg 'mg.priou.co.uk';
17+
prayerRequestFromEmail: process.env.APPSETTINGS_PRAYER_REQUEST_FROM_EMAIL ?? 'unknown',
18+
prayerRequestRecipientEmail: process.env.APPSETTINGS_PRAYER_REQUEST_RECIPIENT_EMAIL ?? 'unknown',
19+
branchName: process.env.APPSETTINGS_BRANCH_NAME ?? 'unknown',
20+
gitSha: process.env.APPSETTINGS_GIT_SHA ?? 'unknown',
1021
};
1122

1223
export { config };

src/server/src/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import path from 'path';
66

77
import { config } from './config';
88
import { logger } from './logging';
9-
import { routes } from './routes';
9+
import { routes } from './routes/index';
1010

1111
const isDevelopment = process.env.NODE_ENV === 'development';
1212

@@ -19,7 +19,7 @@ app.use(
1919
scriptSrc: ["'self'", "'unsafe-inline'", 'storage.googleapis.com', 'www.google-analytics.com'],
2020
frameSrc: ['www.youtube.com', 'www.youtube-nocookie.com'],
2121
},
22-
}),
22+
})
2323
);
2424
app.use(logger);
2525
app.use(routes);
@@ -37,5 +37,5 @@ app.use(async (ctx) => {
3737
app.listen(config.port);
3838

3939
console.log(
40-
`Server running on port ${config.port}; static files served from ${publicPath}, SPA template from ${indexHtmlPath}`,
40+
`Server running on port ${config.port}; static files served from ${publicPath}, SPA template from ${indexHtmlPath}`
4141
);

src/server/src/routes.ts

-96
This file was deleted.

src/server/src/routes/index.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { koaBody } from 'koa-body';
2+
import Router from 'koa-router';
3+
// import * as Mailgun from 'mailgun-js';
4+
5+
import { prayerRequestPOST } from './prayerRequestPOST';
6+
import { statusGET } from './statusGET';
7+
8+
const router = new Router();
9+
10+
router.get('/api/Status', statusGET());
11+
router.post('/api/PrayerRequest', koaBody(), prayerRequestPOST());
12+
13+
export const routes = router.routes();
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import FormData from 'form-data';
2+
import Router from 'koa-router';
3+
import Mailgun from 'mailgun.js';
4+
5+
import { config } from '../config';
6+
7+
export function prayerRequestPOST(): Router.IMiddleware<unknown, unknown> {
8+
return async (ctx, _next) => {
9+
// Invokes the method to send emails given the above data with the helper library
10+
try {
11+
const { email, prayFor } = ctx.request.body;
12+
13+
if (!config.apiKey || !config.domain) {
14+
throw new Error('APPSETTINGS_API_KEY and / or APPSETTINGS_DOMAIN not configured');
15+
}
16+
17+
if (!config.prayerRequestFromEmail || !config.prayerRequestRecipientEmail) {
18+
throw new Error(
19+
'APPSETTINGS_PRAYER_REQUEST_FROM_EMAIL and / or APPSETTINGS_PRAYER_REQUEST_RECIPIENT_EMAIL not configured'
20+
);
21+
}
22+
23+
// We pass the api_key and domain to the wrapper, or it won't be able to identify + send emails
24+
// const mailgun = new Mailgun({ apiKey, domain });
25+
const mailgun = new Mailgun(FormData);
26+
const mg = mailgun.client({ username: 'api', key: config.apiKey });
27+
28+
const prayerRequest = {
29+
from: email, // prayerRequestFromEmail,
30+
to: config.prayerRequestRecipientEmail,
31+
subject: 'Please could you pray for me',
32+
text: `Hi,
33+
34+
I'd love it if you could pray for me about this:
35+
36+
${prayFor}`,
37+
};
38+
// await mailgun.messages().send(prayerRequest);
39+
await mg.messages.create(config.domain, prayerRequest);
40+
41+
const text = `Thank you for your prayer request.
42+
43+
You are in our thoughts and prayers.
44+
45+
Your Poor Clare sisters, Arundel.`;
46+
47+
const html = `<html>
48+
<head>
49+
<title>Thank you for your prayer request.</title>
50+
</head>
51+
<body>
52+
<div>
53+
<img src="https://www.poorclaresarundel.org/prayer-request-image.webp" />
54+
</div>
55+
<div style="padding:10px;font-family: Verdana, Helvetica, Sans-Serif;">
56+
<p>Thank you for your prayer request.</p>
57+
58+
<p>You are in our thoughts and prayers.</p>
59+
60+
<p>Your Poor Clare sisters, Arundel.</p>
61+
</div>
62+
</body>
63+
</html>`;
64+
65+
const reassuringResponse = {
66+
from: config.prayerRequestFromEmail,
67+
to: email,
68+
subject: 'Your prayer request',
69+
text,
70+
html,
71+
};
72+
// await mailgun.messages().send(reassuringResponse);
73+
await mg.messages.create(config.domain, reassuringResponse);
74+
75+
ctx.body = { ok: true, text: 'Thanks for sending your prayer request - we will pray.' };
76+
} catch (exc) {
77+
console.error(exc instanceof Error ? exc.message : exc);
78+
79+
ctx.body = {
80+
success: false,
81+
text: `Your prayer request has not been sent - please try mailing: ${config.prayerRequestFromEmail}`,
82+
};
83+
}
84+
};
85+
}

src/server/src/routes/statusGET.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Router from 'koa-router';
2+
3+
import { config } from '../config';
4+
5+
export function statusGET(): Router.IMiddleware<unknown, unknown> {
6+
return async (ctx, _next) => {
7+
try {
8+
const { branchName, gitSha } = config;
9+
ctx.body = { branchName, gitSha };
10+
} catch (exc) {
11+
console.error(exc instanceof Error ? exc.message : exc);
12+
13+
ctx.status = 500;
14+
ctx.body = {
15+
text: `There is a problem with the server. Please try again later.`,
16+
};
17+
}
18+
};
19+
}

0 commit comments

Comments
 (0)