- Added package.json with dependencies and scripts for building and testing the API. - Implemented DIContainer for managing service instances (Cosmos DB, Key Vault). - Created createDonation function to handle donation creation and Stripe payment processing. - Implemented getDonations function for fetching donations with pagination and filtering. - Defined types for Donation, Volunteer, Program, and API responses. - Configured TypeScript with tsconfig.json for strict type checking and output settings. - Developed deployment scripts for production and simple deployments to Azure. - Created Bicep templates for infrastructure setup including Cosmos DB, Key Vault, and Function App. - Added parameters for deployment configuration in main.parameters.json. - Configured static web app settings in staticwebapp.config.json for routing and security.
324 lines
8.0 KiB
Bicep
324 lines
8.0 KiB
Bicep
@description('Environment (dev, staging, prod)')
|
|
param environment string = 'prod'
|
|
|
|
@description('Azure region for resources')
|
|
param location string = resourceGroup().location
|
|
|
|
@description('Stripe public key for payments')
|
|
@secure()
|
|
param stripePublicKey string
|
|
|
|
// Variables
|
|
var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 6)
|
|
|
|
// Cosmos DB Account
|
|
resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-cosmos'
|
|
location: location
|
|
kind: 'GlobalDocumentDB'
|
|
properties: {
|
|
databaseAccountOfferType: 'Standard'
|
|
consistencyPolicy: {
|
|
defaultConsistencyLevel: 'Session'
|
|
}
|
|
locations: [
|
|
{
|
|
locationName: location
|
|
failoverPriority: 0
|
|
isZoneRedundant: false
|
|
}
|
|
]
|
|
capabilities: [
|
|
{
|
|
name: 'EnableServerless'
|
|
}
|
|
]
|
|
backupPolicy: {
|
|
type: 'Periodic'
|
|
periodicModeProperties: {
|
|
backupIntervalInMinutes: 240
|
|
backupRetentionIntervalInHours: 720
|
|
backupStorageRedundancy: 'Local'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cosmos DB Database
|
|
resource cosmosDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2023-04-15' = {
|
|
parent: cosmosAccount
|
|
name: 'MiraclesInMotion'
|
|
properties: {
|
|
resource: {
|
|
id: 'MiraclesInMotion'
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cosmos DB Containers
|
|
resource donationsContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = {
|
|
parent: cosmosDatabase
|
|
name: 'donations'
|
|
properties: {
|
|
resource: {
|
|
id: 'donations'
|
|
partitionKey: {
|
|
paths: ['/id']
|
|
kind: 'Hash'
|
|
}
|
|
indexingPolicy: {
|
|
indexingMode: 'consistent'
|
|
automatic: true
|
|
includedPaths: [
|
|
{
|
|
path: '/*'
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
resource volunteersContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = {
|
|
parent: cosmosDatabase
|
|
name: 'volunteers'
|
|
properties: {
|
|
resource: {
|
|
id: 'volunteers'
|
|
partitionKey: {
|
|
paths: ['/id']
|
|
kind: 'Hash'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
resource programsContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = {
|
|
parent: cosmosDatabase
|
|
name: 'programs'
|
|
properties: {
|
|
resource: {
|
|
id: 'programs'
|
|
partitionKey: {
|
|
paths: ['/id']
|
|
kind: 'Hash'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Key Vault
|
|
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
|
name: 'mim${environment}${uniqueSuffix}kv'
|
|
location: location
|
|
properties: {
|
|
sku: {
|
|
family: 'A'
|
|
name: 'standard'
|
|
}
|
|
tenantId: tenant().tenantId
|
|
accessPolicies: []
|
|
enabledForDeployment: false
|
|
enabledForDiskEncryption: false
|
|
enabledForTemplateDeployment: true
|
|
enableSoftDelete: true
|
|
softDeleteRetentionInDays: 90
|
|
enableRbacAuthorization: true
|
|
}
|
|
}
|
|
|
|
// Application Insights
|
|
resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-insights'
|
|
location: location
|
|
kind: 'web'
|
|
properties: {
|
|
Application_Type: 'web'
|
|
WorkspaceResourceId: logAnalyticsWorkspace.id
|
|
}
|
|
}
|
|
|
|
// Log Analytics Workspace
|
|
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-logs'
|
|
location: location
|
|
properties: {
|
|
sku: {
|
|
name: 'PerGB2018'
|
|
}
|
|
retentionInDays: 30
|
|
}
|
|
}
|
|
|
|
// Storage Account for Functions
|
|
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
|
|
name: 'mim${environment}${uniqueSuffix}st'
|
|
location: location
|
|
sku: {
|
|
name: 'Standard_LRS'
|
|
}
|
|
kind: 'StorageV2'
|
|
properties: {
|
|
accessTier: 'Hot'
|
|
supportsHttpsTrafficOnly: true
|
|
minimumTlsVersion: 'TLS1_2'
|
|
}
|
|
}
|
|
|
|
// App Service Plan
|
|
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-plan'
|
|
location: location
|
|
sku: {
|
|
name: 'Y1'
|
|
tier: 'Dynamic'
|
|
}
|
|
properties: {
|
|
reserved: false
|
|
}
|
|
}
|
|
|
|
// Function App
|
|
resource functionApp 'Microsoft.Web/sites@2023-01-01' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-func'
|
|
location: location
|
|
kind: 'functionapp'
|
|
identity: {
|
|
type: 'SystemAssigned'
|
|
}
|
|
properties: {
|
|
serverFarmId: appServicePlan.id
|
|
siteConfig: {
|
|
appSettings: [
|
|
{
|
|
name: 'AzureWebJobsStorage'
|
|
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
|
|
}
|
|
{
|
|
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
|
|
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
|
|
}
|
|
{
|
|
name: 'WEBSITE_CONTENTSHARE'
|
|
value: toLower('mim-${environment}-func')
|
|
}
|
|
{
|
|
name: 'FUNCTIONS_EXTENSION_VERSION'
|
|
value: '~4'
|
|
}
|
|
{
|
|
name: 'FUNCTIONS_WORKER_RUNTIME'
|
|
value: 'node'
|
|
}
|
|
{
|
|
name: 'WEBSITE_NODE_DEFAULT_VERSION'
|
|
value: '~18'
|
|
}
|
|
{
|
|
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
|
|
value: appInsights.properties.InstrumentationKey
|
|
}
|
|
{
|
|
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
|
|
value: appInsights.properties.ConnectionString
|
|
}
|
|
{
|
|
name: 'COSMOS_CONNECTION_STRING'
|
|
value: cosmosAccount.listConnectionStrings().connectionStrings[0].connectionString
|
|
}
|
|
{
|
|
name: 'COSMOS_DATABASE_NAME'
|
|
value: 'MiraclesInMotion'
|
|
}
|
|
{
|
|
name: 'KEY_VAULT_URL'
|
|
value: keyVault.properties.vaultUri
|
|
}
|
|
{
|
|
name: 'STRIPE_PUBLIC_KEY'
|
|
value: stripePublicKey
|
|
}
|
|
]
|
|
}
|
|
httpsOnly: true
|
|
}
|
|
}
|
|
|
|
// SignalR Service
|
|
resource signalR 'Microsoft.SignalRService/signalR@2023-02-01' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-signalr'
|
|
location: location
|
|
sku: {
|
|
name: 'Free_F1'
|
|
capacity: 1
|
|
}
|
|
kind: 'SignalR'
|
|
properties: {
|
|
features: [
|
|
{
|
|
flag: 'ServiceMode'
|
|
value: 'Serverless'
|
|
}
|
|
]
|
|
cors: {
|
|
allowedOrigins: ['*']
|
|
}
|
|
}
|
|
}
|
|
|
|
// Static Web App
|
|
resource staticWebApp 'Microsoft.Web/staticSites@2023-01-01' = {
|
|
name: 'mim-${environment}-${uniqueSuffix}-web'
|
|
location: 'Central US'
|
|
sku: {
|
|
name: 'Free'
|
|
}
|
|
properties: {
|
|
buildProperties: {
|
|
outputLocation: 'dist'
|
|
apiLocation: ''
|
|
appLocation: '/'
|
|
}
|
|
stagingEnvironmentPolicy: 'Enabled'
|
|
}
|
|
}
|
|
|
|
// Key Vault Secrets
|
|
resource cosmosConnectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
|
|
parent: keyVault
|
|
name: 'cosmos-connection-string'
|
|
properties: {
|
|
value: cosmosAccount.listConnectionStrings().connectionStrings[0].connectionString
|
|
}
|
|
}
|
|
|
|
resource signalRConnectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
|
|
parent: keyVault
|
|
name: 'signalr-connection-string'
|
|
properties: {
|
|
value: signalR.listKeys().primaryConnectionString
|
|
}
|
|
}
|
|
|
|
// RBAC Assignments for Function App
|
|
resource keyVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
|
name: guid(keyVault.id, functionApp.id, 'Key Vault Secrets User')
|
|
scope: keyVault
|
|
properties: {
|
|
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') // Key Vault Secrets User
|
|
principalId: functionApp.identity.principalId
|
|
principalType: 'ServicePrincipal'
|
|
}
|
|
}
|
|
|
|
// Outputs
|
|
output resourceGroupName string = resourceGroup().name
|
|
output cosmosAccountName string = cosmosAccount.name
|
|
output functionAppName string = functionApp.name
|
|
output staticWebAppName string = staticWebApp.name
|
|
output keyVaultName string = keyVault.name
|
|
output appInsightsName string = appInsights.name
|
|
output signalRName string = signalR.name
|
|
output functionAppUrl string = 'https://${functionApp.properties.defaultHostName}'
|
|
output staticWebAppUrl string = 'https://${staticWebApp.properties.defaultHostname}'
|