constructor()

in cdk/lib/mobile-save-for-later.ts [29:155]


  constructor(scope: App, id: string, props: MobileSaveForLaterProps) {
    super(scope, id, props);

    const yamlTemplateFilePath = join(
      __dirname,
      "../..",
      "mobile-save-for-later/conf/cfn.yaml"
    );
    const yamlDefinedResources = new CfnInclude(this, "YamlTemplate", {
      templateFile: yamlTemplateFilePath,
    });

    const app = "mobile-save-for-later";

    const commonLambdaProps = {
      runtime: Runtime.JAVA_21,
      app,
      fileName: `${app}.jar`,
    };

    const commonEnvironmentVariables = {
      App: app,
      Stack: this.stack,
      Stage: this.stage,
      IdentityApiHost: props.identityApiHost,
      IdentityOktaIssuerUrl: props.identityOktaIssuerUrl,
      IdentityOktaAudience: props.identityOktaAudience,
    };

    const saveArticlesLambda = new GuLambdaFunction(
      this,
      "save-articles-lambda",
      {
        handler: "com.gu.sfl.lambda.SaveArticlesLambda::handleRequest",
        functionName: `mobile-save-for-later-SAVE-cdk-${this.stage}`,
        timeout: Duration.seconds(60),
        environment: {
          ...commonEnvironmentVariables,
          SavedArticleLimit: "1000",
        },
        ...commonLambdaProps,
      }
    );

    const fetchArticlesLambda = new GuLambdaFunction(
      this,
      "fetch-articles-lambda",
      {
        handler: "com.gu.sfl.lambda.FetchArticlesLambda::handleRequest",
        functionName: `mobile-save-for-later-FETCH-cdk-${this.stage}`,
        timeout: Duration.seconds(20),
        reservedConcurrentExecutions: props.reservedConcurrentExecutions,
        environment: commonEnvironmentVariables,
        ...commonLambdaProps,
      }
    );

    [saveArticlesLambda, fetchArticlesLambda].map((lambda) => {
      lambda.addToRolePolicy(
        new PolicyStatement({
          actions: [
            "dynamodb:GetItem",
            "dynamodb:PutItem",
            "dynamodb:UpdateItem",
            "dynamodb:Query",
          ],
          resources: [
            yamlDefinedResources
              .getResource("SaveForLaterDynamoTable")
              // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#aws-resource-dynamodb-table-return-values
              .getAtt("Arn")
              .toString(),
          ],
        })
      );
    });

    const saveForLaterApi = new GuApiGatewayWithLambdaByPath(this, {
      app,
      restApiName: `${app}-api-${this.stage}`,
      monitoringConfiguration: props.monitoringConfiguration,
      targets: [
        {
          path: "/syncedPrefs/me/savedArticles",
          httpMethod: "POST",
          lambda: saveArticlesLambda,
        },
        {
          path: "/syncedPrefs/me",
          httpMethod: "GET",
          lambda: fetchArticlesLambda,
        },
      ],
    });

    // N.B. we cannot use GuCertificate here as we deploy to eu-west-1 but the certificate must be created in us-east-1.
    // https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-edge-optimized-custom-domain-name.html
    const certificateArn = `arn:aws:acm:us-east-1:${this.account}:certificate/${props.certificateId}`;

    const cfnDomainName = new CfnDomainName(this, "ApiDomainName", {
      domainName: props.domainName,
      certificateArn,
      securityPolicy: "TLS_1_2",
    });

    new CfnBasePathMapping(this, "ApiMapping", {
      domainName: cfnDomainName.ref,
      restApiId: saveForLaterApi.api.restApiId,
      stage: saveForLaterApi.api.deploymentStage.stageName,
    });

    new CfnRecordSetGroup(this, "ApiRoute53", {
      hostedZoneId: props.hostedZoneId,
      recordSets: [
        {
          name: props.domainName,
          type: "A",
          aliasTarget: {
            dnsName: cfnDomainName.attrDistributionDomainName,
            // This magical value is taken from the AWS docs:
            // https://docs.amazonaws.cn/en_us/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget-1.html#aws-properties-route53-aliastarget-1-properties
            hostedZoneId: "Z2FDTNDATAQYW2",
          },
        },
      ],
    });
  }