constructor()

in chime-sdk-components/backend-cdk/lib/lti-construct.ts [17:275]


    constructor(parent: Construct, name: string, props: ChimeLTIBackendProps) {
        super(parent, name);
        const meetingsTable = new dynamodb.Table(this, 'meetings', {
            partitionKey: {
              name: 'eventId',
              type: dynamodb.AttributeType.STRING
            },
            removalPolicy: cdk.RemovalPolicy.DESTROY,
            timeToLiveAttribute: 'TTL',
            billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,            
        });

        const rolesTable = new dynamodb.Table(this, 'roles', {
          partitionKey: {
            name: 'RoleId',
            type: dynamodb.AttributeType.STRING
          },
          removalPolicy: cdk.RemovalPolicy.DESTROY,
          billingMode: dynamodb.BillingMode.PAY_PER_REQUEST
        });

        const participantsTable = new dynamodb.Table(this, 'participants', {
          partitionKey: {
            name: 'externalUserId',
            type: dynamodb.AttributeType.STRING
          },
          removalPolicy: cdk.RemovalPolicy.DESTROY,
          timeToLiveAttribute: 'TTL',
          billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,            
      });

        new DynamoDBSeeder(this, 'JsonFileSeeder', {
          table: rolesTable,
          seeds: Seeds.fromJsonFile('./src/roles.json'),
        });

        const lambdaRole = new iam.Role(this, 'lambdaRole', {
          assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
          inlinePolicies: {
            ['chimePolicy']: new iam.PolicyDocument( { statements: [new iam.PolicyStatement({
              resources: ['*'],
              actions: ['chime:*',
                        'lambda:*']})]})
          },
          managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole") ]
        })

        const setupLambda = new lambda.Function(this, 'setup', {
          code: lambda.Code.fromAsset("./src/setup"),
          handler: 'setup.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });

        const endLambda = new lambda.Function(this, 'end', {
          code: lambda.Code.fromAsset("./src/end"),
          handler: 'end.handler',
          role: lambdaRole,          
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });        
          
        const queryLambda = new lambda.Function(this, 'query', {
          code: lambda.Code.fromAsset("./src/query"),
          handler: 'query.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });

        const infoLambda = new lambda.Function(this, 'info', {
          code: lambda.Code.fromAsset("./src/info"),
          handler: 'info.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });

        const attendeeLambda = new lambda.Function(this, 'attendee', {
          code: lambda.Code.fromAsset("./src/attendee"),
          handler: 'attendee.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });        

        const modifyLambda = new lambda.Function(this, 'modify', {
          code: lambda.Code.fromAsset("./src/modify"),
          handler: 'modify.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName
          },
        });

        const parseLogsLambda = new lambda.Function(this, 'parseLogs', {
          code: lambda.Code.fromAsset("./src/parseLogs"),
          handler: 'parse.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            PARTICIPANT_TABLE_NAME: participantsTable.tableName,
            CHIME_CUSTOM_EVENT_BUS_NAME: CHIME_CUSTOM_EVENT_BUS_NAME,
            CHIME_CUSTOM_EVENT_SOURCE_NAME: CHIME_CUSTOM_EVENT_SOURCE_NAME,
          },
        });        
        
        const authLambda = new lambda.Function(this, 'auth', {
          code: lambda.Code.fromAsset("./src/auth"),
          handler: 'auth.handler',
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            JWK_URI: props.public_jwk_url.toString()
          },
        });  
        
        const customChimeEventBus = new events.EventBus(this, 'CustomChimeEventsBus', {
          eventBusName: CHIME_CUSTOM_EVENT_BUS_NAME,
        })

        new events.Rule(this, 'CustomChimeEventsRule', {
          description: 'Capture augmented logs provided by parse lambda',
          enabled: true,
          eventBus: customChimeEventBus,
          eventPattern: {  "source": [CHIME_CUSTOM_EVENT_SOURCE_NAME] },
          targets: [  new targets.CloudWatchLogGroup(new logs.LogGroup(this, 'CustomChimeEventsLogGroup', {
            logGroupName: CHIME_CUSTOM_EVENT_LOG_GROUP_NAME
          })) ]
        })
        new events.Rule(this, 'EventBridgeRule', {
          description: 'Capture Logs',
          enabled: true,
          eventPattern: {  "source": ["aws.chime"] },
          targets: [  new targets.CloudWatchLogGroup(new logs.LogGroup(this, 'LogGroup')),
                      new targets.LambdaFunction(parseLogsLambda)]
        })

        new events.Rule(this, 'EndMeetingEventBridgeRule', {
          description: 'End Meeting Rule',
          enabled: true,
          eventPattern: {
            "source": ["aws.chime"],
            "detail": {
              "eventType": ["chime:MeetingEnded"] }
          },
          targets: [new targets.LambdaFunction(endLambda)],
        })  

        const joinLambda = new lambda.Function(this, 'join', {
          code: lambda.Code.fromAsset("./src/join", {exclude: ['yarn.lock']}),
          handler: 'join.handler',
          role: lambdaRole,
          runtime: lambda.Runtime.NODEJS_14_X,
          timeout: Duration.seconds(60),
          environment: {
            MEETINGS_TABLE_NAME: meetingsTable.tableName,
            ROLE_TABLE_NAME: rolesTable.tableName,
            PARTICIPANT_TABLE_NAME: participantsTable.tableName
          },
        });


        const apiAuth = new apigateway.TokenAuthorizer(this, 'ltiAuthorizer', {
          handler: authLambda,
          resultsCacheTtl: Duration.seconds(0)
        });

        const api = new apigateway.RestApi(this, 'ltiApi', {
          defaultCorsPreflightOptions: {
            allowOrigins: apigateway.Cors.ALL_ORIGINS,
            allowMethods: ['POST', 'OPTIONS'] // this is also the default
          },
          endpointConfiguration: {
            types: [ apigateway.EndpointType.EDGE ]
          }
        });
       
        const setup = api.root.addResource('setup');
        const setupProxy = setup.addProxy({defaultIntegration: new apigateway.LambdaIntegration(setupLambda), anyMethod: false})
        setupProxy.addMethod('POST', new apigateway.LambdaIntegration(setupLambda), {
          authorizer: apiAuth
        })

        const join = api.root.addResource('join');
        const joinProxy = join.addProxy({defaultIntegration: new apigateway.LambdaIntegration(joinLambda), anyMethod: false})
        joinProxy.addMethod('POST', new apigateway.LambdaIntegration(joinLambda), {
          authorizer: apiAuth});

        const query = api.root.addResource('query');
        const queryProxy = query.addProxy({defaultIntegration: new apigateway.LambdaIntegration(queryLambda), anyMethod: false})
        queryProxy.addMethod('POST', new apigateway.LambdaIntegration(queryLambda), {
          authorizer: apiAuth});          

        const info = api.root.addResource('info');
        const infoProxy = info.addProxy({defaultIntegration: new apigateway.LambdaIntegration(joinLambda), anyMethod: false})
        infoProxy.addMethod('POST', new apigateway.LambdaIntegration(infoLambda), {
          authorizer: apiAuth});          

        const end = api.root.addResource('end');
        const endProxy = end.addProxy({defaultIntegration: new apigateway.LambdaIntegration(joinLambda), anyMethod: false})        
        endProxy.addMethod('POST', new apigateway.LambdaIntegration(endLambda), {
          authorizer: apiAuth});          

        const attendee = api.root.addResource('attendee');
        const attendeeProxy = attendee.addProxy({defaultIntegration: new apigateway.LambdaIntegration(joinLambda), anyMethod: false})        
        attendeeProxy.addMethod('POST', new apigateway.LambdaIntegration(attendeeLambda), {
          authorizer: apiAuth});                  

        const modifyUser = api.root.addResource('modifyUser');
        const modifyUserProxy = modifyUser.addProxy({defaultIntegration: new apigateway.LambdaIntegration(joinLambda), anyMethod: false})        
        modifyUserProxy.addMethod('POST', new apigateway.LambdaIntegration(modifyLambda), {
          authorizer: apiAuth});      
        

        meetingsTable.grantReadWriteData(setupLambda);
        rolesTable.grantReadWriteData(setupLambda);
        meetingsTable.grantReadWriteData(joinLambda);
        rolesTable.grantReadWriteData(joinLambda);
        participantsTable.grantWriteData(joinLambda);
        meetingsTable.grantReadWriteData(queryLambda);
        rolesTable.grantReadWriteData(queryLambda);
        meetingsTable.grantReadWriteData(infoLambda);
        rolesTable.grantReadWriteData(infoLambda);
        rolesTable.grantReadWriteData(modifyLambda);
        meetingsTable.grantReadWriteData(modifyLambda);
        rolesTable.grantReadWriteData(endLambda);
        meetingsTable.grantReadWriteData(endLambda);
        rolesTable.grantReadWriteData(attendeeLambda);
        meetingsTable.grantReadWriteData(attendeeLambda);
        participantsTable.grantReadWriteData(parseLogsLambda)        

  // DEFINE SSM PARAMETERS FOR FRONTEND STACK REFERENCE
        new ssm.StringParameter(this, "chimeBackendApiEndpoint", {
          description: "The backend API for the Chime SDK Meetings backend",
          parameterName: "/chime/web/backendUrl",
          stringValue: api.url
        }
    );
  };