From fe4471e8fda5d1b1f398ae234103e04132b8e749 Mon Sep 17 00:00:00 2001 From: Jake Ginnivan Date: Wed, 6 Nov 2024 11:18:43 +0800 Subject: [PATCH] Add cors and announcement route --- .github/workflows/ci.yml | 2 ++ infra/app/ddd.bicep | 20 +++++++++++ infra/main.bicep | 7 ++++ infra/main.parameters.json | 7 ++-- website/app/lib/http.server.ts | 5 +++ website/app/routes/app-agenda-grid.tsx | 7 +++- website/app/routes/app-agenda-sessions.tsx | 7 +++- website/app/routes/app-agenda-speakers.tsx | 7 +++- website/app/routes/app-announcements.tsx | 42 ++++++++++++++++++++++ website/app/routes/app-config.tsx | 2 ++ website/app/routes/app-content.$.tsx | 7 +++- 11 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 website/app/routes/app-announcements.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d044e7..a3d61a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,8 @@ jobs: AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} # TODO Replace this PAT with a GitHub App GH_CONTENT_TOKEN: ${{ secrets.GH_CONTENT_TOKEN }} + GOOGLE_FORMS_API_KEY: ${{ secrets.GOOGLE_FORMS_API_KEY }} + GOOGLE_FORMS_FORM_ID: ${{ secrets.GOOGLE_FORMS_FORM_ID }} steps: - name: Checkout diff --git a/infra/app/ddd.bicep b/infra/app/ddd.bicep index 19d5348..296494b 100644 --- a/infra/app/ddd.bicep +++ b/infra/app/ddd.bicep @@ -10,6 +10,10 @@ param gitHubOrganization string param gitHubRepo string @secure() param gitHubToken string +@secure() +param googleFormsApiKey string +@secure() +param googleFormsFileId string param exists bool resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { @@ -83,6 +87,14 @@ resource app 'Microsoft.App/containerApps@2024-03-01' = { name: 'session-secret' value: sessionSecret } + { + name: 'google-forms-api-key' + value: googleFormsApiKey + } + { + name: 'google-forms-file-id' + value: googleFormsFileId + } ] } template: { @@ -115,6 +127,14 @@ resource app 'Microsoft.App/containerApps@2024-03-01' = { name: 'SESSION_SECRET' secretRef: 'session-secret' } + { + name: 'GOOGLE_FORMS_API_KEY' + secretRef: 'google-forms-api-key' + } + { + name: 'GOOGLE_FORMS_FILE_ID' + secretRef: 'google-forms-file-id' + } ] resources: { diff --git a/infra/main.bicep b/infra/main.bicep index 2e65af0..dc8c3a7 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -22,6 +22,11 @@ param gitHubRepo string @secure() param gitHubToken string +@secure() +param googleFormsApiKey string +@secure() +param googleFormsFileId string + // Tags that should be applied to all resources. // // Note that 'azd-service-name' tags should be applied separately to service host resources. @@ -111,6 +116,8 @@ module ddd './app/ddd.bicep' = { gitHubOrganization: gitHubOrganization gitHubRepo: gitHubRepo gitHubToken: gitHubToken + googleFormsApiKey: googleFormsApiKey + googleFormsFileId: googleFormsFileId } scope: rg } diff --git a/infra/main.parameters.json b/infra/main.parameters.json index c680937..5be054f 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -39,8 +39,11 @@ "gitHubRepo": { "value": "dddperth" }, - "gitHubToken": { - "value": "${GH_CONTENT_TOKEN}" + "googleFormsApiKey": { + "value": "${GOOGLE_FORMS_API_KEY}" + }, + "googleFormsFormId": { + "value": "${GOOGLE_FORMS_FORM_ID}" } } } diff --git a/website/app/lib/http.server.ts b/website/app/lib/http.server.ts index 508ace9..9edbe37 100644 --- a/website/app/lib/http.server.ts +++ b/website/app/lib/http.server.ts @@ -7,6 +7,11 @@ export const CACHE_CONTROL = { * back button */ DEFAULT: 'max-age=300', + + /** + * Add 1 minutes cache control for announcements + */ + announce: 'max-age=60', /** * Keep it in the browser (and CDN) for 5 minutes so when they click * back/forward/etc. it's super fast. SWR for 1 week on CDN so it stays fast, diff --git a/website/app/routes/app-agenda-grid.tsx b/website/app/routes/app-agenda-grid.tsx index 286e9f2..b829411 100644 --- a/website/app/routes/app-agenda-grid.tsx +++ b/website/app/routes/app-agenda-grid.tsx @@ -23,7 +23,12 @@ export async function loader({ context }: LoaderFunctionArgs) { const schedule = schedules[0] - return json(schedule, { headers: { 'Cache-Control': CACHE_CONTROL.conf } }) + return json(schedule, { + headers: { + 'Cache-Control': CACHE_CONTROL.conf, + 'Access-Control-Allow-Origin': '*', + }, + }) } export const headers: HeadersFunction = ({ loaderHeaders }) => { // Inherit the caching headers from the loader so we don't cache 404s diff --git a/website/app/routes/app-agenda-sessions.tsx b/website/app/routes/app-agenda-sessions.tsx index 213d687..50bdd52 100644 --- a/website/app/routes/app-agenda-sessions.tsx +++ b/website/app/routes/app-agenda-sessions.tsx @@ -20,7 +20,12 @@ export async function loader({ context }: LoaderFunctionArgs) { }) : [] - return json(sessions, { headers: { 'Cache-Control': CACHE_CONTROL.conf } }) + return json(sessions, { + headers: { + 'Cache-Control': CACHE_CONTROL.conf, + 'Access-Control-Allow-Origin': '*', + }, + }) } export const headers: HeadersFunction = ({ loaderHeaders }) => { diff --git a/website/app/routes/app-agenda-speakers.tsx b/website/app/routes/app-agenda-speakers.tsx index 8cd1244..4510e86 100644 --- a/website/app/routes/app-agenda-speakers.tsx +++ b/website/app/routes/app-agenda-speakers.tsx @@ -20,7 +20,12 @@ export async function loader({ context }: LoaderFunctionArgs) { }) : [] - return json(speakers, { headers: { 'Cache-Control': CACHE_CONTROL.conf } }) + return json(speakers, { + headers: { + 'Cache-Control': CACHE_CONTROL.conf, + 'Access-Control-Allow-Origin': '*', + }, + }) } export const headers: HeadersFunction = ({ loaderHeaders }) => { diff --git a/website/app/routes/app-announcements.tsx b/website/app/routes/app-announcements.tsx new file mode 100644 index 0000000..d3e441b --- /dev/null +++ b/website/app/routes/app-announcements.tsx @@ -0,0 +1,42 @@ +import { json } from '@remix-run/server-runtime' +import { CACHE_CONTROL } from '~/lib/http.server' + +export type GoogleFormUpdates = { + Timestamp: string + Message: string +} + +/** This route is used by the app for on the day announcements */ +export async function loader() { + const apiKey = process.env.GOOGLE_FORMS_API_KEY + const fileId = process.env.GOOGLE_FORMS_FORM_ID + if (!apiKey || !fileId) { + return new Response(JSON.stringify({ message: 'No Google Forms API key or form ID' }), { status: 404 }) + } + + const BASE_URL = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&key=${apiKey}` + + const response = await fetch(BASE_URL, { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + }) + + const responseData = (await response.json()) as GoogleFormUpdates[] + + const announcementData = responseData + .map((row) => { + return { createdTime: row.Timestamp, update: row.Message } + }) + .sort((a, b) => { + return new Date(b.createdTime).getTime() - new Date(a.createdTime).getTime() + }) + + return json(announcementData, { + headers: { + 'Cache-Control': CACHE_CONTROL.announce, + 'Access-Control-Allow-Origin': '*', + }, + }) +} diff --git a/website/app/routes/app-config.tsx b/website/app/routes/app-config.tsx index 73b31eb..db35778 100644 --- a/website/app/routes/app-config.tsx +++ b/website/app/routes/app-config.tsx @@ -1,5 +1,6 @@ import { json, LoaderFunctionArgs } from '@remix-run/server-runtime' import { YearSponsors } from '~/lib/config-types' +import { CACHE_CONTROL } from '~/lib/http.server' /** This route is used by the app or integrations to understand the state of the conference */ export function loader({ context }: LoaderFunctionArgs) { @@ -18,6 +19,7 @@ export function loader({ context }: LoaderFunctionArgs) { return json(data, { headers: { + 'Cache-Control': CACHE_CONTROL.doc, 'Access-Control-Allow-Origin': '*', }, }) diff --git a/website/app/routes/app-content.$.tsx b/website/app/routes/app-content.$.tsx index f6dee66..fb36bb5 100644 --- a/website/app/routes/app-content.$.tsx +++ b/website/app/routes/app-content.$.tsx @@ -35,7 +35,12 @@ export async function loader({ params, request, context }: LoaderFunctionArgs) { post: post.code, conferenceState: context.conferenceState, }, - { headers: { 'Cache-Control': CACHE_CONTROL.doc, 'Access-Control-Allow-Origin': '*' } }, + { + headers: { + 'Cache-Control': CACHE_CONTROL.doc, + 'Access-Control-Allow-Origin': '*', + }, + }, ) }