console/deployment/index.ts
Laurin Quast 6540155fc7
feat: replace auth0 with supertokens (#303)
* add supertoken container to docker-compose file

* yeah I am sorry this one big commit and I am ashamed of it

* use logOut function

* feat: show header on 404 page

* feat: better handling for organization cookie when not authenticated

* wrap it

* check session within server side props

* add is_admin flag user migration

* simplify and annotate the config

* fix: handle status codes + fix email/password sign up with import from auth0

* no hardcoded env pls

* decode process.env

* secure update user id mapping via a key

* fix: login form

* lol we don't need to hit the API

* fix: do graphql api authorization via authorization header instead of cookie

* implement isAdmin flag

* fix: types :)

* skipit

* yo we can run this

* set env variables

* disable because it annoys the hell out of me

* use the right host

* add not about token length

* refactor: decode environment variables

* feat: store external user id from guthub/google provider in the database

* workaround supertokens omitting null values from the token

* re-enable check

* i have no time for this shit

* add missing env variable

* fix: email test; missing domain extension

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>

* fix: env names

* fix: link google account to the correct db record

* feat: email confirmation emails

* ?

* bump ts-node

* fix types

* omit package form the bundle

* remove it from dependencies...

* add emails apckage to dev deps

* resolve eslint issues

* remove comments

* update dev info + change env variable (no need to expose it on the frontend)

* use correct user id lol

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 09:38:31 +02:00

265 lines
6.9 KiB
TypeScript

import * as pulumi from '@pulumi/pulumi';
import { DeploymentEnvironment } from './types';
import { deployDbMigrations } from './services/db-migrations';
import { deployTokens } from './services/tokens';
import { deployWebhooks } from './services/webhooks';
import { deployEmails } from './services/emails';
import { deploySchema } from './services/schema';
import { deployUsage } from './services/usage';
import { deployUsageIngestor } from './services/usage-ingestor';
import { deployGraphQL } from './services/graphql';
import { deployApp } from './services/app';
import { deployLandingPage } from './services/landing-page';
import { deployDocs } from './services/docs';
import { deployRedis } from './services/redis';
import { deployKafka } from './services/kafka';
import { deployMetrics } from './services/observability';
import { deployCloudflare } from './services/cloudflare';
import { deployCloudflarePolice } from './services/police';
import { deployBotKube } from './services/bot-kube';
import { deployProxy } from './services/proxy';
import { deployClickhouse } from './services/clickhouse';
import { deployUsageEstimation } from './services/usage-estimation';
import { deploySuperTokens } from './services/supertokens';
import { createPackageHelper } from './utils/pack';
import * as azure from '@pulumi/azure';
import { optimizeAzureCluster } from './utils/azure-helpers';
import { deployRateLimit } from './services/rate-limit';
import { deployStripeBilling } from './services/billing';
import * as random from '@pulumi/random';
const packageHelper = createPackageHelper();
optimizeAzureCluster();
const envName = pulumi.getStack();
const commonConfig = new pulumi.Config('common');
const appDns = 'app';
const docsDns = 'docs';
const rootDns = commonConfig.require('dnsZone');
const appHostname = `${appDns}.${rootDns}`;
const docsHostname = `${docsDns}.${rootDns}`;
const heartbeatsConfig = new pulumi.Config('heartbeats');
const emailConfig = new pulumi.Config('email');
const resourceGroup = new azure.core.ResourceGroup(`hive-${envName}-rg`, {
location: azure.Locations.EastUS,
});
const storageAccount = new azure.storage.Account(`hive${envName}`, {
resourceGroupName: resourceGroup.name,
accountReplicationType: 'LRS',
accountTier: 'Standard',
accountKind: 'StorageV2',
allowBlobPublicAccess: true,
});
const storageContainer = new azure.storage.Container('deploy-artifacts', {
storageAccountName: storageAccount.name,
containerAccessType: 'blob',
});
const deploymentEnv: DeploymentEnvironment = {
ENVIRONMENT: envName,
NODE_ENV: 'production',
DEPLOYED_DNS: appHostname,
};
deployBotKube({ envName });
deployMetrics({ envName });
const cloudflare = deployCloudflare({
envName,
rootDns,
});
deployCloudflarePolice({ envName, rootDns });
const redisApi = deployRedis({ deploymentEnv });
const kafkaApi = deployKafka();
const clickhouseApi = deployClickhouse();
const dbMigrations = deployDbMigrations({
storageContainer,
packageHelper,
clickhouse: clickhouseApi,
kafka: kafkaApi,
deploymentEnv,
});
const tokensApi = deployTokens({
packageHelper,
storageContainer,
deploymentEnv,
dbMigrations,
heartbeat: heartbeatsConfig.get('tokens'),
});
const webhooksApi = deployWebhooks({
packageHelper,
storageContainer,
deploymentEnv,
redis: redisApi,
heartbeat: heartbeatsConfig.get('webhooks'),
});
const emailsApi = deployEmails({
packageHelper,
storageContainer,
deploymentEnv,
redis: redisApi,
email: {
token: emailConfig.requireSecret('token'),
from: emailConfig.require('from'),
messageStream: emailConfig.require('messageStream'),
},
// heartbeat: heartbeatsConfig.get('emails'),
});
const usageEstimationApi = deployUsageEstimation({
packageHelper,
storageContainer,
deploymentEnv,
clickhouse: clickhouseApi,
dbMigrations,
});
const billingApi = deployStripeBilling({
packageHelper,
storageContainer,
deploymentEnv,
dbMigrations,
usageEstimator: usageEstimationApi,
});
const rateLimitApi = deployRateLimit({
packageHelper,
storageContainer,
deploymentEnv,
dbMigrations,
usageEstimator: usageEstimationApi,
emails: emailsApi,
});
const usageApi = deployUsage({
packageHelper,
storageContainer,
deploymentEnv,
tokens: tokensApi,
kafka: kafkaApi,
dbMigrations,
rateLimit: rateLimitApi,
});
const usageIngestorApi = deployUsageIngestor({
clickhouse: clickhouseApi,
kafka: kafkaApi,
packageHelper,
storageContainer,
deploymentEnv,
dbMigrations,
heartbeat: heartbeatsConfig.get('usageIngestor'),
});
const schemaApi = deploySchema({
packageHelper,
storageContainer,
deploymentEnv,
redis: redisApi,
});
const supertokensApiKey = new random.RandomPassword('supertokens-api-key', { length: 31, special: false });
const auth0LegacyMigrationKey = new random.RandomPassword('auth0-legacy-migration-key', { length: 69, special: false });
const oauthConfig = new pulumi.Config('oauth');
const githubConfig = {
clientId: oauthConfig.requireSecret('githubClient'),
clientSecret: oauthConfig.requireSecret('githubSecret'),
};
const googleConfig = {
clientId: oauthConfig.requireSecret('googleClient'),
clientSecret: oauthConfig.requireSecret('googleSecret'),
};
const supertokens = deploySuperTokens({ apiKey: supertokensApiKey.result });
const graphqlApi = deployGraphQL({
clickhouse: clickhouseApi,
packageHelper,
storageContainer,
deploymentEnv,
tokens: tokensApi,
webhooks: webhooksApi,
schema: schemaApi,
dbMigrations,
redis: redisApi,
usage: usageApi,
cloudflare,
usageEstimator: usageEstimationApi,
rateLimit: rateLimitApi,
billing: billingApi,
emails: emailsApi,
supertokensConfig: {
apiKey: supertokensApiKey.result,
endpoint: supertokens.localEndpoint,
},
auth0Config: {
internalApiKey: auth0LegacyMigrationKey.result,
},
});
const app = deployApp({
deploymentEnv,
graphql: graphqlApi,
dbMigrations,
packageHelper,
storageContainer,
supertokensConfig: {
apiKey: supertokensApiKey.result,
endpoint: supertokens.localEndpoint,
},
auth0Config: {
internalApiKey: auth0LegacyMigrationKey.result,
},
githubConfig,
googleConfig,
emailsEndpoint: emailsApi.localEndpoint,
});
const landingPage = deployLandingPage({
rootDns,
packageHelper,
storageContainer,
});
const docs = deployDocs({
rootDns,
packageHelper,
storageContainer,
});
const proxy = deployProxy({
rootDns,
appHostname,
docsHostname,
app,
landingPage,
docs,
graphql: graphqlApi,
usage: usageApi,
});
export const graphqlApiServiceId = graphqlApi.service.id;
export const usageApiServiceId = usageApi.service.id;
export const usageIngestorApiServiceId = usageIngestorApi.service.id;
export const tokensApiServiceId = tokensApi.service.id;
export const schemaApiServiceId = schemaApi.service.id;
export const webhooksApiServiceId = webhooksApi.service.id;
export const appId = app.deployment.id;
export const publicIp = proxy!.status.loadBalancer.ingress[0].ip;