From 3105e37bdb1b49dfc710b98a4780af152b30ba2d Mon Sep 17 00:00:00 2001 From: Reinder Vos de Wael Date: Mon, 8 Jul 2024 09:47:48 -0400 Subject: [PATCH 1/7] Add or update the Azure App Service build and deployment workflow config --- ...elopment_cliniciantoolkit(development).yml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/development_cliniciantoolkit(development).yml diff --git a/.github/workflows/development_cliniciantoolkit(development).yml b/.github/workflows/development_cliniciantoolkit(development).yml new file mode 100644 index 0000000..17033fa --- /dev/null +++ b/.github/workflows/development_cliniciantoolkit(development).yml @@ -0,0 +1,62 @@ +# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy +# More GitHub Actions for Azure: https://github.com/Azure/actions + +name: Build and deploy Node.js app to Azure Web App - cliniciantoolkit + +on: + push: + branches: + - development + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js version + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: npm install, build, and test + run: | + npm install + npm run build --if-present + npm run test --if-present + + - name: Zip artifact for deployment + run: zip release.zip ./* -r + + - name: Upload artifact for deployment job + uses: actions/upload-artifact@v3 + with: + name: node-app + path: release.zip + + deploy: + runs-on: ubuntu-latest + needs: build + environment: + name: 'development' + url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + + steps: + - name: Download artifact from build job + uses: actions/download-artifact@v3 + with: + name: node-app + + - name: Unzip artifact for deployment + run: unzip release.zip + + - name: 'Deploy to Azure Web App' + id: deploy-to-webapp + uses: azure/webapps-deploy@v2 + with: + app-name: 'cliniciantoolkit' + slot-name: 'development' + package: . + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D8F19C70B5EA48B29386C08288419993 }} \ No newline at end of file From 35ebe1bd2104efd1d6db8fd2202c39f7007794d4 Mon Sep 17 00:00:00 2001 From: Reinder Vos de Wael Date: Mon, 8 Jul 2024 10:27:12 -0400 Subject: [PATCH 2/7] refactor: Merge deployment YAMLs --- ...niciantoolkit.yml => azure_deployment.yml} | 5 +- ...elopment_cliniciantoolkit(development).yml | 62 ------------------- 2 files changed, 3 insertions(+), 64 deletions(-) rename .github/workflows/{main_cliniciantoolkit.yml => azure_deployment.yml} (89%) delete mode 100644 .github/workflows/development_cliniciantoolkit(development).yml diff --git a/.github/workflows/main_cliniciantoolkit.yml b/.github/workflows/azure_deployment.yml similarity index 89% rename from .github/workflows/main_cliniciantoolkit.yml rename to .github/workflows/azure_deployment.yml index 2a1bc50..7a29c74 100644 --- a/.github/workflows/main_cliniciantoolkit.yml +++ b/.github/workflows/azure_deployment.yml @@ -7,6 +7,7 @@ on: push: branches: - main + - development workflow_dispatch: env: @@ -45,7 +46,7 @@ jobs: runs-on: ubuntu-latest needs: build environment: - name: "Production" + name: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} steps: @@ -62,6 +63,6 @@ jobs: uses: azure/webapps-deploy@v3 with: app-name: "cliniciantoolkit" - slot-name: "Production" + slot-name: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} package: . publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_9A3AB102193241559E3EADB479BA0400 }} diff --git a/.github/workflows/development_cliniciantoolkit(development).yml b/.github/workflows/development_cliniciantoolkit(development).yml deleted file mode 100644 index 17033fa..0000000 --- a/.github/workflows/development_cliniciantoolkit(development).yml +++ /dev/null @@ -1,62 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy -# More GitHub Actions for Azure: https://github.com/Azure/actions - -name: Build and deploy Node.js app to Azure Web App - cliniciantoolkit - -on: - push: - branches: - - development - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Node.js version - uses: actions/setup-node@v3 - with: - node-version: '20.x' - - - name: npm install, build, and test - run: | - npm install - npm run build --if-present - npm run test --if-present - - - name: Zip artifact for deployment - run: zip release.zip ./* -r - - - name: Upload artifact for deployment job - uses: actions/upload-artifact@v3 - with: - name: node-app - path: release.zip - - deploy: - runs-on: ubuntu-latest - needs: build - environment: - name: 'development' - url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - - steps: - - name: Download artifact from build job - uses: actions/download-artifact@v3 - with: - name: node-app - - - name: Unzip artifact for deployment - run: unzip release.zip - - - name: 'Deploy to Azure Web App' - id: deploy-to-webapp - uses: azure/webapps-deploy@v2 - with: - app-name: 'cliniciantoolkit' - slot-name: 'development' - package: . - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D8F19C70B5EA48B29386C08288419993 }} \ No newline at end of file From 5779f3d485af5c0717b4cf27fdb607d34f46480c Mon Sep 17 00:00:00 2001 From: Reinder Vos de Wael Date: Mon, 8 Jul 2024 10:51:45 -0400 Subject: [PATCH 3/7] fix: update secret --- .github/workflows/azure_deployment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/azure_deployment.yml b/.github/workflows/azure_deployment.yml index 7a29c74..115f999 100644 --- a/.github/workflows/azure_deployment.yml +++ b/.github/workflows/azure_deployment.yml @@ -65,4 +65,4 @@ jobs: app-name: "cliniciantoolkit" slot-name: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} package: . - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_9A3AB102193241559E3EADB479BA0400 }} + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D8F19C70B5EA48B29386C08288419993 }} From 12d6f8b7f46a07a8b4db3f530a8a68f93bd1c7ea Mon Sep 17 00:00:00 2001 From: Reinder Vos de Wael Date: Mon, 8 Jul 2024 13:05:16 -0400 Subject: [PATCH 4/7] feat: add user management Remove comment --- src/hooks.server.ts | 13 +++++++- src/lib/server/azure.ts | 2 +- src/lib/server/{secrets.ts => environment.ts} | 2 ++ src/lib/server/sql.ts | 2 +- src/routes/+layout.server.ts | 31 +++++++++++++++++++ src/routes/api/health/+server.ts | 2 +- src/routes/api/intake-report/[id]/+server.ts | 2 +- src/routes/api/llm/+server.ts | 2 +- src/routes/api/markdown2docx/+server.ts | 2 +- src/routes/templates/+page.svelte | 10 ++++-- 10 files changed, 58 insertions(+), 10 deletions(-) rename src/lib/server/{secrets.ts => environment.ts} (91%) create mode 100644 src/routes/+layout.server.ts diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 8395c54..a13e11f 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,12 +1,14 @@ import { logger } from "$lib/server/logging" import { randomUUID } from "crypto" import { performance } from "perf_hooks" +import { pool } from "$lib/server/sql" +import { DEVELOPMENT_USER } from "$lib/server/environment" export async function handle({ event, resolve }) { const requestId = randomUUID() const startTime = performance.now() - const user = event.request.headers.get("X-MS-CLIENT-PRINCIPAL-NAME") || "development.user@example.com" + const user = event.request.headers.get("X-MS-CLIENT-PRINCIPAL-NAME") || DEVELOPMENT_USER logger.info({ type: `Request`, method: event.request.method, @@ -17,6 +19,15 @@ export async function handle({ event, resolve }) { event.request.headers.set("X-Request-ID", requestId) event.request.headers.set("X-User", user) + const userQuery = { + text: "INSERT INTO users (email) VALUES ($1) ON CONFLICT DO NOTHING", + values: [user] + } + await pool.connect().then(async client => { + await client.query(userQuery) + client.release() + }) + const response = await resolve(event) const endTime = performance.now() diff --git a/src/lib/server/azure.ts b/src/lib/server/azure.ts index 4b930b3..0f61d25 100644 --- a/src/lib/server/azure.ts +++ b/src/lib/server/azure.ts @@ -1,4 +1,4 @@ -import { AZURE_BLOB_ACCOUNT_NAME, AZURE_BLOB_SAS } from "./secrets" +import { AZURE_BLOB_ACCOUNT_NAME, AZURE_BLOB_SAS } from "./environment" import { logger } from "./logging" if (!AZURE_BLOB_ACCOUNT_NAME || !AZURE_BLOB_SAS) { diff --git a/src/lib/server/secrets.ts b/src/lib/server/environment.ts similarity index 91% rename from src/lib/server/secrets.ts rename to src/lib/server/environment.ts index 118a2ea..e8afbf3 100644 --- a/src/lib/server/secrets.ts +++ b/src/lib/server/environment.ts @@ -11,3 +11,5 @@ export const AZURE_FUNCTION_PYTHON_KEY = env.AZURE_FUNCTION_PYTHON_KEY export const AZURE_BLOB_ACCOUNT_NAME = env.AZURE_BLOB_ACCOUNT_NAME export const AZURE_BLOB_SAS = env.AZURE_BLOB_SAS + +export const DEVELOPMENT_USER = env.DEVELOPMENT_USER diff --git a/src/lib/server/sql.ts b/src/lib/server/sql.ts index 811d8dd..88fb528 100644 --- a/src/lib/server/sql.ts +++ b/src/lib/server/sql.ts @@ -1,5 +1,5 @@ import pkg from "pg" -import { POSTGRES_HOST, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, POSTGRES_PORT } from "./secrets" +import { POSTGRES_HOST, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, POSTGRES_PORT } from "./environment" const { Pool } = pkg const config = { diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts new file mode 100644 index 0000000..88b66bc --- /dev/null +++ b/src/routes/+layout.server.ts @@ -0,0 +1,31 @@ +import { DEVELOPMENT_USER } from "$lib/server/environment.js" +import { pool } from "$lib/server/sql" + +type User = { + id: number + email: string + is_admin: boolean + is_alpha_user: boolean +} + +export async function load({ request }) { + const userEmail = request.headers.get("X-MS-CLIENT-PRINCIPAL-NAME") || DEVELOPMENT_USER + const userQuery = { + text: "SELECT * FROM users WHERE email = $1", + values: [userEmail] + } + const user: User = await pool.connect().then(async client => { + const result = await client.query(userQuery) + client.release() + return result.rows[0] + }) + + if (!user) { + return { + status: 401, + error: "User not found." + } + } + + return { user } +} diff --git a/src/routes/api/health/+server.ts b/src/routes/api/health/+server.ts index 02b5a90..2fb604d 100644 --- a/src/routes/api/health/+server.ts +++ b/src/routes/api/health/+server.ts @@ -1,5 +1,5 @@ import { logger } from "$lib/server/logging" -import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/secrets" +import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/environment" export async function GET() { logger.info("Warming up the server.") diff --git a/src/routes/api/intake-report/[id]/+server.ts b/src/routes/api/intake-report/[id]/+server.ts index 4e40201..03c30c2 100644 --- a/src/routes/api/intake-report/[id]/+server.ts +++ b/src/routes/api/intake-report/[id]/+server.ts @@ -1,5 +1,5 @@ import { logger } from "$lib/server/logging" -import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/secrets" +import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/environment" export async function GET({ params, fetch }) { const id = params.id diff --git a/src/routes/api/llm/+server.ts b/src/routes/api/llm/+server.ts index 6b03539..ebd2b93 100644 --- a/src/routes/api/llm/+server.ts +++ b/src/routes/api/llm/+server.ts @@ -1,6 +1,6 @@ import { env } from "$env/dynamic/private" import { logger } from "$lib/server/logging" -import { AZURE_FUNCTION_PYTHON_KEY } from "$lib/server/secrets" +import { AZURE_FUNCTION_PYTHON_KEY } from "$lib/server/environment" export async function POST({ fetch, request }) { logger.info("Making LLM request.") diff --git a/src/routes/api/markdown2docx/+server.ts b/src/routes/api/markdown2docx/+server.ts index 5438795..a395e43 100644 --- a/src/routes/api/markdown2docx/+server.ts +++ b/src/routes/api/markdown2docx/+server.ts @@ -1,5 +1,5 @@ import { logger } from "$lib/server/logging" -import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/secrets" +import { AZURE_FUNCTION_PYTHON_KEY, AZURE_FUNCTION_PYTHON_URL } from "$lib/server/environment" export async function POST({ fetch, request }) { logger.info("Converting markdown to docx") diff --git a/src/routes/templates/+page.svelte b/src/routes/templates/+page.svelte index e6954dc..83b93fc 100644 --- a/src/routes/templates/+page.svelte +++ b/src/routes/templates/+page.svelte @@ -8,6 +8,8 @@ import SelectedNodes from "./SelectedNodes.svelte" import MarkdownEditor from "$lib/components/MarkdownEditor.svelte" + export let data + let selectedNodes: DecisionTree[] = [] let tabSet: number = 0 let editable: boolean = false @@ -44,9 +46,11 @@