From 1cad98f1c6d2674e539479998415b6add7224a9f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 7 Jul 2020 11:20:11 -0500 Subject: [PATCH 001/140] GD-1626: "Spin up" the Aurora server-less instance --- .../templates/givesource-aurora.yml | 112 ++++++++++++++++++ .../cloudformation/templates/givesource.yml | 2 + 2 files changed, 114 insertions(+) create mode 100644 packages/cloudformation/templates/givesource-aurora.yml diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml new file mode 100644 index 00000000..20911a77 --- /dev/null +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -0,0 +1,112 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: AWS Aurora resources for Givesource(R) +Parameters: + AppName: + Description: "Givesource" + Type: String + Default: givesource + EnvType: + Description: "Environment type (eg, dev, qa, prod)" + Type: String + Default: dev + DBClusterName: + Description: "Givesource Aurora RDS cluster name" #I think this probably needs something else + Type: String + Default: givesource-rds-cluster + DatabaseName: + Description: "Givesource Aurora RDS database name" + Type: String + Default: givesource-database + DBMasterUserName: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database admin account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: admin_user + DBSubnetList: # this might need to work with only two, script was built for three + Description: "List of subnets for the Aurora RDS cluster" + Type: List + ConstraintDescription: "must be a list of at least two existing subnets associated with at least two different availability zones." + Resources: + DBSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: CloudFormation managed DB subnet group. + SubnetIds: + - !Select [0, !Ref DBSubnetList ] + - !Select [1, !Ref DBSubnetList ] + DBSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub "${AWS::StackName}:${EnvType}-AuroraUserSecret" + Description: RDS database auto-generated user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}' + GenerateStringKey: "password" + PasswordLength: 30 + ExcludeCharacters: '"@/\' + Tags: + - Key: AppName + Value: !Ref AppName + RDSCluster: + Type: AWS::RDS::DBCluster + Properties: + DBClusterIdentifier: !Ref DBClusterName + MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:username}}' ]] + MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:password}}' ]] + DatabaseName: !Ref DatabaseName + Engine: aurora + EngineMode: serverless + EngineVersion: 5.6.10a + ScalingConfiguration: + AutoPause: true + MaxCapacity: 16 + MinCapacity: 1 + SecondsUntilAutoPause: 900 # 15 min + DBSubnetGroupName: + Ref: DBSubnetGroup + Outputs: + StackName: + Description: Aurora Stack Name + Value: !Ref AWS::StackName + Export: + Name: !Sub ${AWS::StackName}-StackName + + DatabaseName: + Description: Aurora Database Name + Value: !Ref DatabaseName + Export: + Name: !Sub ${AWS::StackName}-DatabaseName + + DatabaseClusterArn: + Description: Aurora Cluster ARN + Value: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${DBClusterName} + Export: + Name: !Sub ${AWS::StackName}-DatabaseClusterArn + + DatabaseSecretArn: + Description: Aurora Secret ARN + Value: !Ref DBSecret + Export: + Name: !Sub ${AWS::StackName}-DatabaseSecretArn + + DatabaseClusterID: + Description: Aurora Cluster ID + Value: !Ref RDSCluster + Export: + Name: !Sub ${AWS::StackName}-DatabaseClusterID + + AuroraDbURL: + Description: Aurora Database URL + Value: !GetAtt RDSCluster.Endpoint.Address + Export: + Name: !Sub ${AWS::StackName}-DatabaseURL + + DatabaseMasterUserName: + Description: Aurora Database User + Value: !Ref DBMasterUserName + Export: + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index a0912b34..a63a6e7c 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -101,6 +101,8 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-dynamo.yml TimeoutInMinutes: 40 + ### Going to have to add the Aurora Stuff here I think DM: Debug + S3Stack: Type: AWS::CloudFormation::Stack Properties: From cbd932115198ef1bd370a5585d7d24480568c784 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 7 Jul 2020 11:34:46 -0500 Subject: [PATCH 002/140] GD-1626: "Spin up" the Aurora server-less instance (givesource.yml) --- packages/cloudformation/templates/givesource.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index a63a6e7c..4f038081 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -101,7 +101,13 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-dynamo.yml TimeoutInMinutes: 40 - ### Going to have to add the Aurora Stuff here I think DM: Debug + AuroraDbStack: ### Going to have to add the Aurora Stuff here I think DM: Debug (also will need to do a release) + Type: AWS::CloudFormation::Stack + Properties: + Parameters: + StackName: !Ref AWS::StackName + TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml + TimeoutInMinutes: 40 S3Stack: Type: AWS::CloudFormation::Stack @@ -341,6 +347,7 @@ Resources: DependsOn: - CognitoSnsCallerRole - DynamoDbStack + - AuroraDbStack - LambdaRole - S3Stack @@ -688,6 +695,7 @@ Resources: - ApiDeployStack - CustomStack - DynamoDbStack + - AuroraDbStack - S3Stack MonitoringStack: From 6e10552433e286f9d9c01a46f43f6d2e8b96f45e Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 7 Jul 2020 15:16:54 -0500 Subject: [PATCH 003/140] GD-1626: "Spin up" the Aurora server-less instance (givesource.yml) --- .../templates/givesource-aurora.yml | 159 +++++++++--------- 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 20911a77..94264073 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -6,10 +6,6 @@ Parameters: Description: "Givesource" Type: String Default: givesource - EnvType: - Description: "Environment type (eg, dev, qa, prod)" - Type: String - Default: dev DBClusterName: Description: "Givesource Aurora RDS cluster name" #I think this probably needs something else Type: String @@ -17,7 +13,7 @@ Parameters: DatabaseName: Description: "Givesource Aurora RDS database name" Type: String - Default: givesource-database + Default: givesourceDB DBMasterUserName: AllowedPattern: "[a-zA-Z0-9_]+" ConstraintDescription: must be between 1 to 16 alphanumeric characters. @@ -25,88 +21,91 @@ Parameters: MaxLength: '16' MinLength: '1' Type: String - Default: admin_user + Default: adminUser DBSubnetList: # this might need to work with only two, script was built for three Description: "List of subnets for the Aurora RDS cluster" Type: List ConstraintDescription: "must be a list of at least two existing subnets associated with at least two different availability zones." - Resources: - DBSubnetGroup: - Type: AWS::RDS::DBSubnetGroup - Properties: - DBSubnetGroupDescription: CloudFormation managed DB subnet group. - SubnetIds: - - !Select [0, !Ref DBSubnetList ] - - !Select [1, !Ref DBSubnetList ] - DBSecret: - Type: AWS::SecretsManager::Secret - Properties: - Name: !Sub "${AWS::StackName}:${EnvType}-AuroraUserSecret" - Description: RDS database auto-generated user password - GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}' - GenerateStringKey: "password" - PasswordLength: 30 - ExcludeCharacters: '"@/\' - Tags: - - Key: AppName - Value: !Ref AppName - RDSCluster: - Type: AWS::RDS::DBCluster - Properties: - DBClusterIdentifier: !Ref DBClusterName - MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:username}}' ]] - MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:password}}' ]] - DatabaseName: !Ref DatabaseName - Engine: aurora - EngineMode: serverless - EngineVersion: 5.6.10a - ScalingConfiguration: - AutoPause: true - MaxCapacity: 16 - MinCapacity: 1 - SecondsUntilAutoPause: 900 # 15 min - DBSubnetGroupName: - Ref: DBSubnetGroup - Outputs: - StackName: - Description: Aurora Stack Name - Value: !Ref AWS::StackName - Export: - Name: !Sub ${AWS::StackName}-StackName + Default: "subnet-ea69d68e,subnet-e01c0fcc" + StackName: + Type: String +Resources: + DBSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: CloudFormation managed DB subnet group. + SubnetIds: + - !Select [0, !Ref DBSubnetList ] + - !Select [1, !Ref DBSubnetList ] + DBSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub "${AWS::StackName}-AuroraUserSecret" + Description: RDS database auto-generated user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}' + GenerateStringKey: "password" + PasswordLength: 30 + ExcludeCharacters: '"@/\' + Tags: + - Key: AppName + Value: !Ref AppName + RDSCluster: + Type: AWS::RDS::DBCluster + Properties: + DBClusterIdentifier: !Ref DBClusterName + MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:username}}' ]] + MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:password}}' ]] + DatabaseName: !Ref DatabaseName + Engine: aurora + EngineMode: serverless + EngineVersion: 5.6.10a + ScalingConfiguration: + AutoPause: true + MaxCapacity: 16 + MinCapacity: 1 + SecondsUntilAutoPause: 900 # 15 min + DBSubnetGroupName: + Ref: DBSubnetGroup +Outputs: + StackName: + Description: Aurora Stack Name + Value: !Ref AWS::StackName + Export: + Name: !Sub ${AWS::StackName}-StackName - DatabaseName: - Description: Aurora Database Name - Value: !Ref DatabaseName - Export: - Name: !Sub ${AWS::StackName}-DatabaseName + DatabaseName: + Description: Aurora Database Name + Value: !Ref DatabaseName + Export: + Name: !Sub ${AWS::StackName}-DatabaseName - DatabaseClusterArn: - Description: Aurora Cluster ARN - Value: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${DBClusterName} - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterArn + DatabaseClusterArn: + Description: Aurora Cluster ARN + Value: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${DBClusterName} + Export: + Name: !Sub ${AWS::StackName}-DatabaseClusterArn - DatabaseSecretArn: - Description: Aurora Secret ARN - Value: !Ref DBSecret - Export: - Name: !Sub ${AWS::StackName}-DatabaseSecretArn + DatabaseSecretArn: + Description: Aurora Secret ARN + Value: !Ref DBSecret + Export: + Name: !Sub ${AWS::StackName}-DatabaseSecretArn - DatabaseClusterID: - Description: Aurora Cluster ID - Value: !Ref RDSCluster - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterID + DatabaseClusterID: + Description: Aurora Cluster ID + Value: !Ref RDSCluster + Export: + Name: !Sub ${AWS::StackName}-DatabaseClusterID - AuroraDbURL: - Description: Aurora Database URL - Value: !GetAtt RDSCluster.Endpoint.Address - Export: - Name: !Sub ${AWS::StackName}-DatabaseURL + AuroraDbURL: + Description: Aurora Database URL + Value: !GetAtt RDSCluster.Endpoint.Address + Export: + Name: !Sub ${AWS::StackName}-DatabaseURL - DatabaseMasterUserName: - Description: Aurora Database User - Value: !Ref DBMasterUserName - Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file + DatabaseMasterUserName: + Description: Aurora Database User + Value: !Ref DBMasterUserName + Export: + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file From ea139eb91565194269e14c4b617e00256a2b2685 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 7 Jul 2020 15:28:13 -0500 Subject: [PATCH 004/140] GD-1626: "Spin up" the Aurora server-less instance --- packages/cloudformation/templates/givesource-aurora.yml | 4 ++-- packages/cloudformation/templates/givesource.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 94264073..3929f3d2 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -7,7 +7,7 @@ Parameters: Type: String Default: givesource DBClusterName: - Description: "Givesource Aurora RDS cluster name" #I think this probably needs something else + Description: "Givesource Aurora RDS cluster name" Type: String Default: givesource-rds-cluster DatabaseName: @@ -22,7 +22,7 @@ Parameters: MinLength: '1' Type: String Default: adminUser - DBSubnetList: # this might need to work with only two, script was built for three + DBSubnetList: Description: "List of subnets for the Aurora RDS cluster" Type: List ConstraintDescription: "must be a list of at least two existing subnets associated with at least two different availability zones." diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 4f038081..bf358b99 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -101,7 +101,7 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-dynamo.yml TimeoutInMinutes: 40 - AuroraDbStack: ### Going to have to add the Aurora Stuff here I think DM: Debug (also will need to do a release) + AuroraDbStack: Type: AWS::CloudFormation::Stack Properties: Parameters: From bdd7e9f7c6df63c60bba77912c8a02775746637e Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 9 Jul 2020 11:52:09 -0500 Subject: [PATCH 005/140] WIP --- packages/cloudformation/templates/givesource-aurora.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 3929f3d2..99c19443 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -54,8 +54,10 @@ Resources: Type: AWS::RDS::DBCluster Properties: DBClusterIdentifier: !Ref DBClusterName - MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:username}}' ]] - MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref DBSecret, ':SecretString:password}}' ]] +{{=<% %>=}} + MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' + MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' +<%={{ }}=%> DatabaseName: !Ref DatabaseName Engine: aurora EngineMode: serverless @@ -108,4 +110,4 @@ Outputs: Description: Aurora Database User Value: !Ref DBMasterUserName Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName From 888345af3e4cf588430d390007257b63a8b1e06d Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 9 Jul 2020 14:20:55 -0500 Subject: [PATCH 006/140] GD-1626: "Spin up" the Aurora server-less instance --- .../cloudformation/templates/givesource-aurora.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 99c19443..31fb1c3a 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -6,14 +6,10 @@ Parameters: Description: "Givesource" Type: String Default: givesource - DBClusterName: - Description: "Givesource Aurora RDS cluster name" - Type: String - Default: givesource-rds-cluster DatabaseName: Description: "Givesource Aurora RDS database name" Type: String - Default: givesourceDB + Default: givesource DBMasterUserName: AllowedPattern: "[a-zA-Z0-9_]+" ConstraintDescription: must be between 1 to 16 alphanumeric characters. @@ -53,7 +49,6 @@ Resources: RDSCluster: Type: AWS::RDS::DBCluster Properties: - DBClusterIdentifier: !Ref DBClusterName {{=<% %>=}} MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' @@ -84,7 +79,7 @@ Outputs: DatabaseClusterArn: Description: Aurora Cluster ARN - Value: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${DBClusterName} + Value: !Ref RDSCluster Export: Name: !Sub ${AWS::StackName}-DatabaseClusterArn @@ -110,4 +105,4 @@ Outputs: Description: Aurora Database User Value: !Ref DBMasterUserName Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file From a9ff69a03ea02d366bd4401ba7e9c40ebe295a16 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 13 Jul 2020 12:59:01 -0500 Subject: [PATCH 007/140] GD-1626: "Spin up" the Aurora server-less instance --- .../templates/givesource-aurora.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 31fb1c3a..605815d4 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -2,14 +2,6 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS Aurora resources for Givesource(R) Parameters: - AppName: - Description: "Givesource" - Type: String - Default: givesource - DatabaseName: - Description: "Givesource Aurora RDS database name" - Type: String - Default: givesource DBMasterUserName: AllowedPattern: "[a-zA-Z0-9_]+" ConstraintDescription: must be between 1 to 16 alphanumeric characters. @@ -43,9 +35,6 @@ Resources: GenerateStringKey: "password" PasswordLength: 30 ExcludeCharacters: '"@/\' - Tags: - - Key: AppName - Value: !Ref AppName RDSCluster: Type: AWS::RDS::DBCluster Properties: @@ -53,7 +42,6 @@ Resources: MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' <%={{ }}=%> - DatabaseName: !Ref DatabaseName Engine: aurora EngineMode: serverless EngineVersion: 5.6.10a @@ -71,12 +59,6 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-StackName - DatabaseName: - Description: Aurora Database Name - Value: !Ref DatabaseName - Export: - Name: !Sub ${AWS::StackName}-DatabaseName - DatabaseClusterArn: Description: Aurora Cluster ARN Value: !Ref RDSCluster From 598cf1b50febb207d919979e4a9cc298953d403e Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 21 Jul 2020 09:07:02 -0500 Subject: [PATCH 008/140] [GD-1637] Create VPC and subnets * Added vpc.yml to create a VPC with two public subnets which are exported for use in other stacks * Created a billing dashboard --- cloudformation/vpc.yml | 213 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 cloudformation/vpc.yml diff --git a/cloudformation/vpc.yml b/cloudformation/vpc.yml new file mode 100644 index 00000000..88fe50a8 --- /dev/null +++ b/cloudformation/vpc.yml @@ -0,0 +1,213 @@ +--- +Description: Creates the VPC, routing tables, and subnets for Givesource +Mappings: + IpRange: + us-east-1: {'016226103026': '172.32'} + us-east-2: {'016226103026': '172.33'} + us-west-1: {'016226103026': '172.34'} + us-west-2: {'016226103026': '172.35'} + us-east-1: {'948629139753': '172.132'} + us-east-2: {'948629139753': '172.133'} + us-west-1: {'948629139753': '172.134'} + us-west-2: {'948629139753': '172.135'} + +Resources: + internetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: givesource + + vpc: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Sub + - ${IpRange}.0.0/16 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: givesource + - Key: Purpose + Value: The VPC for Givesource + + flowLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub FlowLog/givesource/${vpc} + RetentionInDays: 365 + + flowLogsRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: vpc-flow-logs.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: flowlog-log + PolicyDocument: + Statement: + - Effect: Allow + Action: + - ec2:CreateFlowLogs + Resource: '*' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy + + flowLog: + Type: AWS::EC2::FlowLog + Properties: + DeliverLogsPermissionArn: !GetAtt flowLogsRole.Arn + LogGroupName: !Ref flowLogGroup + ResourceId: !Ref vpc + ResourceType: VPC + TrafficType: ALL + + attachInternetGatewayToVpc: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + InternetGatewayId: !Ref internetGateway + VpcId: !Ref vpc + + publicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: public-givesource + + internetGatewayRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref publicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref internetGateway + + primaryPublicSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref primaryPublicSubnet + RouteTableId: !Ref publicRouteTable + + primaryPublicSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.0.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [0, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Public + - Key: Name + Value: primary-public-givesource + + secondaryPublicSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref secondaryPublicSubnet + RouteTableId: !Ref publicRouteTable + + secondaryPublicSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.2.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [1, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Public + - Key: Name + Value: secondary-givesource + + billingDashboard: + Type: AWS::CloudWatch::Dashboard + Properties: + DashboardName: !Sub givesource-billing-${AWS::Region} + DashboardBody: !Sub + - > + { + "start": "-P6M", + "widgets": [ + { + "type": "metric", + "x": 0, + "y": 12, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/Billing", + "EstimatedCharges", + "Currency", + "USD", + { + "period": 2592000, + "stat": "Maximum" + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "us-east-1" + } + } + ] + } + - {} + +Outputs: + internetGateway: + Description: Internet Gateway for the Givesource VPC + Value: !Ref internetGateway + Export: + Name: givesource-internet-gateway + + vpc: + Description: VPC for Givesource + Value: !Ref vpc + Export: + Name: givesource-vpc + + vpcCidr: + Description: The Cidr of the Givesource VPC + Value: !GetAtt vpc.CidrBlock + Export: + Name: givesource-vpc-cidr + + aclVpc: + Description: Default ACL for the Givesource VPC + Value: !GetAtt vpc.DefaultNetworkAcl + Export: + Name: givesource-vpc-acl + + ipRange: + Description: IP Range for the Givesource VPC + Value: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId'] + Export: + Name: givesource-vpc-ip-range + + primaryPublicSubnet: + Description: Primary Public Subnet for Givesource + Value: !Ref primaryPublicSubnet + Export: + Name: givsource-primary-public-subnet + + secondaryPublicSubnet: + Description: Secondary Public Subnet for Givesource + Value: !Ref secondaryPublicSubnet + Export: + Name: givesource-secondary-public-subnet + From 6a1b46eccfa04ec1f51624c467631876234a7f18 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 21 Jul 2020 15:40:58 -0500 Subject: [PATCH 009/140] GD-1627: Research/Decide/Do the migration and schema --- .../templates/givesource-aurora.yml | 78 +++- .../cloudformation/templates/givesource.yml | 47 ++ packages/lambda/config/webpack.config.js | 3 + packages/lambda/package-lock.json | 61 ++- packages/lambda/package.json | 1 + packages/lambda/src/aws/secretsManager.js | 39 ++ .../lambda/src/database/createSchema/index.js | 411 ++++++++++++++++++ 7 files changed, 629 insertions(+), 11 deletions(-) create mode 100644 packages/lambda/src/aws/secretsManager.js create mode 100644 packages/lambda/src/database/createSchema/index.js diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 605815d4..bac57c11 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -10,21 +10,41 @@ Parameters: MinLength: '1' Type: String Default: adminUser - DBSubnetList: - Description: "List of subnets for the Aurora RDS cluster" - Type: List - ConstraintDescription: "must be a list of at least two existing subnets associated with at least two different availability zones." - Default: "subnet-ea69d68e,subnet-e01c0fcc" StackName: Type: String + DefaultLambdaFunctionTimeout: + Type: Number + LambdaRoleArn: + Type: String + LambdaSecurityGroupId: + Type: String Resources: + GivesourceAuroraSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for aurora + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-aurora + LambdaAuroraIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: allows access from lambda into aurora + GroupId: !GetAtt GivesourceAuroraSecurityGroup.GroupId + IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupId: !Ref LambdaSecurityGroupId DBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: CloudFormation managed DB subnet group. SubnetIds: - - !Select [0, !Ref DBSubnetList ] - - !Select [1, !Ref DBSubnetList ] + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DBSecret: Type: AWS::SecretsManager::Secret Properties: @@ -52,6 +72,50 @@ Resources: SecondsUntilAutoPause: 900 # 15 min DBSubnetGroupName: Ref: DBSubnetGroup + DependsOn: DBSecret + CreateSchemaLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/CreateSchema.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref AWS::StackName + DATABASE_USER: !Ref DBMasterUserName + DATABASE_SECRET_ARN: !Ref DBSecret + AURORA_DB_HOST: !GetAtt RDSCluster.Endpoint.Address + SECRETS_MANAGER_SECRET_ID: !Sub "${AWS::StackName}-AuroraUserSecret" + FunctionName: !Sub |- + ${StackName}-CreateSchema + Handler: "index.handle" + MemorySize: 128 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + DependsOn: RDSCluster +# CreateSchemaLambdaInvokePermission: +# Type: AWS::Lambda::Permission +# Properties: +# FunctionName: !Ref CreateSchemaLambdaFunction +# Action: "lambda:InvokeFunction" +# Principal: "apigateway.amazonaws.com" +# SourceArn: !Ref SnsTopic +# SnsTopic: +# Type: AWS::SNS::Topic +# Properties: +# DisplayName: !Sub ${StackName} Aurora Schema +# Subscription: +# - Endpoint: !GetAtt CreateSchemaLambdaFunction.Arn +# Protocol: lambda Outputs: StackName: Description: Aurora Stack Name diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index bf358b99..c093ced9 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -106,6 +106,9 @@ Resources: Properties: Parameters: StackName: !Ref AWS::StackName + DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] + LambdaRoleArn: !GetAtt RDSSchemaLambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 @@ -300,8 +303,20 @@ Resources: - ssm:DeleteParameter - ssm:GetParameter - ssm:PutParameter + - secretsmanager:GetSecretValue Resource: '*' +# SecretsManagerManagedPolicy: +# Type: AWS::IAM::ManagedPolicy +# Properties: +# PolicyDocument: +# Version: 2012-10-17 +# Statement: +# - Effect: Allow +# Action: +# - secretsmanager:GetSecretValue +# Resource: '*' + LambdaRole: Type: AWS::IAM::Role Properties: @@ -324,6 +339,38 @@ Resources: - !Ref SESManagedPolicy - !Ref SSMManagedPolicy + LambdaSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for lambda + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-lambda + + RDSSchemaLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + - edgelambda.amazonaws.com + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + - !Ref ApiGatewayManagedPolicy + - !Ref CloudFormationManagedPolicy + - !Ref CloudWatchLogsManagedPolicy + - !Ref LambdaManagedPolicy + - !Ref S3ManagedPolicy + - !Ref SSMManagedPolicy + - arn:aws:iam::aws:policy/SecretsManagerReadWrite + CustomStack: Type: AWS::CloudFormation::Stack Properties: diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 885f185a..1707fc43 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -155,6 +155,9 @@ module.exports = { SendDonationNotificationEmail: './src/custom/sendDonationNotificationEmail/index.js', SendDonationsReceiptEmail: './src/custom/sendDonationsReceiptEmail/index.js', SendRegistrationPendingEmail: './src/custom/sendRegistrationPendingEmail/index.js', + + // Database Lambda Functions + CreateSchema: './src/database/createSchema/index.js', }, output: { filename: '[name]/index.js', diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index 290e74e6..ae5c36d5 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -703,6 +703,11 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -1368,8 +1373,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cp-file": { "version": "6.2.0", @@ -4251,6 +4255,51 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -5715,6 +5764,11 @@ "extend-shallow": "^3.0.0" } }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -6417,8 +6471,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid-validate": { "version": "0.0.2", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index fa4191e7..3bc06253 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -23,6 +23,7 @@ "dotenv": "^4.0.0", "json-loader": "^0.5.7", "mime": "^2.2.2", + "mysql": "^2.18.1", "rimraf": "^2.6.1", "validate.js": "0.10.0" }, diff --git a/packages/lambda/src/aws/secretsManager.js b/packages/lambda/src/aws/secretsManager.js new file mode 100644 index 00000000..cddd0bea --- /dev/null +++ b/packages/lambda/src/aws/secretsManager.js @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const AWS = require('aws-sdk'); + +/** + * Secrets Manager constructor + * + * @constructor + */ +function SecretsManager() { +} + +/** + * Get a secret value from the secrets manager + * + * @param region + * @param secretId + * @returns {Promise} + */ +SecretsManager.prototype.getSecretValue = (region, secretId) => { + const secretManger = new AWS.SecretsManager({region: region}); + return secretManger.getSecretValue({SecretId: secretId}).promise(); +}; + +module.exports = SecretsManager; \ No newline at end of file diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js new file mode 100644 index 00000000..b94e5139 --- /dev/null +++ b/packages/lambda/src/database/createSchema/index.js @@ -0,0 +1,411 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const mysql = require("mysql"); +const Request = require('./../../aws/request'); +const SecretsManager = require('./../../aws/secretsManager'); + +exports.handle = function (event, context, callback) { + console.log(JSON.stringify(event)); + const secretsManager = new SecretsManager(); + const request = new Request(event, context); + + request.validate().then(function () { + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) + }).then(function (response) { + + if ('SecretString' in response) { + //Here exec the requests to init the DB + + console.log("Connecting to Aurora"); + let connection = mysql.createConnection({ + host: process.env.AURORA_DB_HOST, + user: process.env.DATABASE_USER, + password: JSON.parse(response.SecretString).password, + ssl: true, + port: 3306 + }); + + connection.connect(function (err) { + if (err) throw err; + console.log('connected!'); /*DM: Debug */ + }); + + connection.query('CREATE DATABASE IF NOT EXISTS `test-db-name` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.changeUser({database: 'test-db-name'}, function (err) { + if (err) throw err; + console.log('switched to test-db-name'); + }); + + console.log('get ready to run query'); /*DM: Debug */ + //create the database + connection.query('DROP TABLE IF EXISTS contents', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query( + 'CREATE TABLE `contents` (' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`parentId` INT(11) NOT NULL DEFAULT 0, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_contents_parent_id_index` (`parentId`))', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS donations', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `donations` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + '`count` INT(11) NOT NULL DEFAULT 0, ' + + '`fees` INT(11) NOT NULL DEFAULT 0, ' + + '`isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + '`paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + + '`subtotal` INT(11) NOT NULL DEFAULT 0, ' + + '`subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + + '`total` INT(11) NOT NULL DEFAULT 0, ' + + '`type` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`donorId` INT(11) NOT NULL DEFAULT 0, ' + + '`note` VARCHAR(255) DEFAULT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + + 'KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + + 'KEY `ix_donations_donor_id` (`donorId`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS donors', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `donors` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + '`address1` VARCHAR(50) NOT NULL, ' + + '`address2` VARCHAR(50) NOT NULL, ' + + '`city` VARCHAR(50) NOT NULL, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`state` VARCHAR(50) NOT NULL, ' + + '`zip` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_donors_email` (`email`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS files', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `files` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`path` VARCHAR(50) NOT NULL, ' + + '`filename` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS messages', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `messages` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`message` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS metrics', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `metrics` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`key` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `nonprofit_donation_tiers` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`amount` INT(11) NOT NULL DEFAULT 0, ' + + '`description` VARCHAR(255) NOT NULL, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS nonprofits', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `nonprofits` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`address1` VARCHAR(50) NOT NULL, ' + + '`address2` VARCHAR(50) NOT NULL, ' + + '`category1` INT(11) NOT NULL DEFAULT 0, ' + + '`category2` INT(11) NOT NULL DEFAULT 0, ' + + '`category3` INT(11) NOT NULL DEFAULT 0, ' + + '`city` VARCHAR(50) NOT NULL, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`state` VARCHAR(50) NOT NULL, ' + + '`zip` VARCHAR(50) NOT NULL, ' + + '`legalName` VARCHAR(50) NOT NULL, ' + + '`legalNameSearch` VARCHAR(50) NOT NULL, ' + + '`logoFileId` INT(11) NOT NULL DEFAULT 0, ' + + '`longDescription` VARCHAR(255) NOT NULL, ' + + '`receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`shortDescription` VARCHAR(50) NOT NULL, ' + + '`slug` VARCHAR(50) NOT NULL, ' + + '`socialSharingDescription` VARCHAR(50) NOT NULL, ' + + '`socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + + '`status` VARCHAR(50) NOT NULL, ' + + '`taxId` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + + 'KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + + 'KEY `ix_nonprofits_slug` (`slug`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS nonprofit_slides', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `nonprofit_slides` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`caption` VARCHAR(50) NOT NULL, ' + + '`embedUrl` VARCHAR(50) NOT NULL, ' + + '`externalId` VARCHAR(50) NOT NULL, ' + + '`thumbnail` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`url` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS payment_transactions', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `payment_transactions` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`billingZip` VARCHAR(50) NOT NULL, ' + + '`creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + + '`creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + + '`creditCardLast4` VARCHAR(50) NOT NULL, ' + + '`creditCardName` VARCHAR(50) NOT NULL, ' + + '`creditCardType` VARCHAR(50) NOT NULL, ' + + '`isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + + '`transactionId` VARCHAR(50) NOT NULL, ' + + '`transactionStatus` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS reports', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `reports` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`status` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS settings', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `settings` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`key` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS sponsors', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `sponsors` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`logoUrl` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`url` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS sponsor_tiers', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `sponsor_tiers` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`size` VARCHAR(50) NOT NULL, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_sponsor_tiers_name` (`name`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('DROP TABLE IF EXISTS users', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + + connection.query('CREATE TABLE `users` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`cognitoId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_users_email` (`email`), ' + + 'KEY `ix_users_cognito_id` (`cognitoId`) ' + + ')', function (err, rows, fields) { + if (err) throw err; + console.log(rows); + }); + connection.end(); + + } + + }).catch(function (err) { + console.log('this mfer errored'); /*DM: Debug */ + console.log(err); /*DM: Debug */ + }); + + callback(); +}; \ No newline at end of file From fd1d5aefcfde0b3d6dd9ce58fd03f37265eef778 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 21 Jul 2020 15:42:07 -0500 Subject: [PATCH 010/140] Adding private subnets: --- cloudformation/vpc.yml | 177 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 3 deletions(-) diff --git a/cloudformation/vpc.yml b/cloudformation/vpc.yml index 88fe50a8..99ac285f 100644 --- a/cloudformation/vpc.yml +++ b/cloudformation/vpc.yml @@ -129,17 +129,176 @@ Resources: - Key: SubnetType Value: Public - Key: Name - Value: secondary-givesource + Value: secondary-public-givesource - billingDashboard: + primaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + primaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt primaryPrivateEip.AllocationId + SubnetId: !Ref primaryPublicSubnet + + primaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: primary-private-givesource + + primaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref primaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref primaryPrivateNatGateway + + primaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.10.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [0, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: primary-private-givesource + + primaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref primaryPrivateSubnet + RouteTableId: !Ref primaryPrivateRouteTable + + secondaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + secondaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt secondaryPrivateEip.AllocationId + SubnetId: !Ref secondaryPublicSubnet + + secondaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref secondaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref secondaryPrivateNatGateway + + secondaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.12.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [1, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref secondaryPrivateSubnet + RouteTableId: !Ref secondaryPrivateRouteTable + + vpcDashboard: Type: AWS::CloudWatch::Dashboard Properties: - DashboardName: !Sub givesource-billing-${AWS::Region} + DashboardName: !Sub givesource-vpc-${AWS::Region} DashboardBody: !Sub - > { "start": "-P6M", "widgets": [ + { + "type": "metric", + "x": 0, + "y": 0, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromSource", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromSource", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "period": 300, + "title": "NAT Gateway Bytes received from clients in your VPC" + } + }, + { + "type": "metric", + "x": 0, + "y": 6, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromDestination", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromDestination", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "title": "NAT Gateway Bytes received from the destination" + } + }, { "type": "metric", "x": 0, @@ -211,3 +370,15 @@ Outputs: Export: Name: givesource-secondary-public-subnet + primaryPrivateSubnet: + Description: Primary Private Subnet for Givesource + Value: !Ref primaryPrivateSubnet + Export: + Name: givsource-primary-private-subnet + + secondaryPrivateSubnet: + Description: Secondary Private Subnet for Givesource + Value: !Ref secondaryPrivateSubnet + Export: + Name: givesource-secondary-private-subnet + From 15fec83c6039103bbef197b187e15eb3d7f60a04 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 21 Jul 2020 15:43:55 -0500 Subject: [PATCH 011/140] WIP --- packages/cloudformation/templates/givesource-aurora.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index bac57c11..bdff8fa7 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -72,6 +72,8 @@ Resources: SecondsUntilAutoPause: 900 # 15 min DBSubnetGroupName: Ref: DBSubnetGroup + VpcSecurityGroupIds: + - !GetAtt GivesourceAuroraSecurityGroup.GroupId DependsOn: DBSecret CreateSchemaLambdaFunction: Type: AWS::Lambda::Function @@ -151,4 +153,4 @@ Outputs: Description: Aurora Database User Value: !Ref DBMasterUserName Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName From 7873b0ccaec6e92678b232e853c61bcf756e8d49 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 21 Jul 2020 15:52:46 -0500 Subject: [PATCH 012/140] WIP --- packages/cloudformation/templates/givesource-aurora.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index bdff8fa7..c082add0 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -65,6 +65,7 @@ Resources: Engine: aurora EngineMode: serverless EngineVersion: 5.6.10a + EnableHttpEndpoint: true ScalingConfiguration: AutoPause: true MaxCapacity: 16 From 454fc3a989b66725bfadb5c40f893d1ef7fe08c9 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 22 Jul 2020 12:24:25 -0500 Subject: [PATCH 013/140] GD-1627: Research/Decide/Do the migration and schema --- .../templates/givesource-aurora.yml | 18 +- .../lambda/src/database/createSchema/index.js | 165 ++++-------------- 2 files changed, 38 insertions(+), 145 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index c082add0..aa4ee7f7 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -105,20 +105,10 @@ Resources: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet DependsOn: RDSCluster -# CreateSchemaLambdaInvokePermission: -# Type: AWS::Lambda::Permission -# Properties: -# FunctionName: !Ref CreateSchemaLambdaFunction -# Action: "lambda:InvokeFunction" -# Principal: "apigateway.amazonaws.com" -# SourceArn: !Ref SnsTopic -# SnsTopic: -# Type: AWS::SNS::Topic -# Properties: -# DisplayName: !Sub ${StackName} Aurora Schema -# Subscription: -# - Endpoint: !GetAtt CreateSchemaLambdaFunction.Arn -# Protocol: lambda + CreateSchemaLambdaCustomResource: + Type: "Custom::CreateSchemaLambdaInvoker" + Properties: + ServiceToken: !GetAtt CreateSchemaLambdaFunction.Arn Outputs: StackName: Description: Aurora Stack Name diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index b94e5139..23f1677c 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -28,8 +28,6 @@ exports.handle = function (event, context, callback) { }).then(function (response) { if ('SecretString' in response) { - //Here exec the requests to init the DB - console.log("Connecting to Aurora"); let connection = mysql.createConnection({ host: process.env.AURORA_DB_HOST, @@ -44,22 +42,15 @@ exports.handle = function (event, context, callback) { console.log('connected!'); /*DM: Debug */ }); - connection.query('CREATE DATABASE IF NOT EXISTS `test-db-name` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { + connection.query('CREATE DATABASE IF NOT EXISTS `givesource` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { if (err) throw err; console.log(rows); }); - connection.changeUser({database: 'test-db-name'}, function (err) { - if (err) throw err; - console.log('switched to test-db-name'); - }); + connection.changeUser({database: 'givesource'}); - console.log('get ready to run query'); /*DM: Debug */ //create the database - connection.query('DROP TABLE IF EXISTS contents', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS contents'); connection.query( 'CREATE TABLE `contents` (' + @@ -72,15 +63,9 @@ exports.handle = function (event, context, callback) { '`value` VARCHAR(50) NOT NULL, ' + '`name` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`), ' + - 'KEY `ix_contents_parent_id_index` (`parentId`))', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + 'KEY `ix_contents_parent_id_index` (`parentId`))'); - connection.query('DROP TABLE IF EXISTS donations', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS donations'); connection.query('CREATE TABLE `donations` ( ' + '`id` INT(11) NOT NULL, ' + @@ -105,15 +90,9 @@ exports.handle = function (event, context, callback) { 'KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + 'KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + 'KEY `ix_donations_donor_id` (`donorId`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS donors', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS donors'); connection.query('CREATE TABLE `donors` ( ' + '`id` INT(11) NOT NULL, ' + @@ -131,15 +110,9 @@ exports.handle = function (event, context, callback) { '`zip` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`), ' + 'KEY `ix_donors_email` (`email`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS files', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS files'); connection.query('CREATE TABLE `files` ( ' + '`id` INT(11) NOT NULL, ' + @@ -148,15 +121,9 @@ exports.handle = function (event, context, callback) { '`path` VARCHAR(50) NOT NULL, ' + '`filename` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS messages', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS messages'); connection.query('CREATE TABLE `messages` ( ' + '`id` INT(11) NOT NULL, ' + @@ -168,15 +135,9 @@ exports.handle = function (event, context, callback) { '`phone` VARCHAR(50) NOT NULL, ' + '`type` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS metrics', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS metrics'); connection.query('CREATE TABLE `metrics` ( ' + '`id` INT(11) NOT NULL, ' + @@ -185,15 +146,9 @@ exports.handle = function (event, context, callback) { '`key` VARCHAR(50) NOT NULL, ' + '`value` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers'); connection.query('CREATE TABLE `nonprofit_donation_tiers` ( ' + '`id` INT(11) NOT NULL, ' + @@ -204,15 +159,9 @@ exports.handle = function (event, context, callback) { '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + 'PRIMARY KEY (`id`), ' + 'KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS nonprofits', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS nonprofits'); connection.query('CREATE TABLE `nonprofits` ( ' + '`id` INT(11) NOT NULL, ' + @@ -245,15 +194,9 @@ exports.handle = function (event, context, callback) { 'KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + 'KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + 'KEY `ix_nonprofits_slug` (`slug`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS nonprofit_slides', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS nonprofit_slides'); connection.query('CREATE TABLE `nonprofit_slides` ( ' + '`id` INT(11) NOT NULL, ' + @@ -270,15 +213,9 @@ exports.handle = function (event, context, callback) { '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + 'PRIMARY KEY (`id`), ' + 'KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS payment_transactions', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS payment_transactions'); connection.query('CREATE TABLE `payment_transactions` ( ' + '`id` INT(11) NOT NULL, ' + @@ -295,15 +232,9 @@ exports.handle = function (event, context, callback) { '`transactionId` VARCHAR(50) NOT NULL, ' + '`transactionStatus` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS reports', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS reports'); connection.query('CREATE TABLE `reports` ( ' + '`id` INT(11) NOT NULL, ' + @@ -314,15 +245,9 @@ exports.handle = function (event, context, callback) { '`fileId` INT(11) NOT NULL DEFAULT 0, ' + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS settings', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS settings'); connection.query('CREATE TABLE `settings` ( ' + '`id` INT(11) NOT NULL, ' + @@ -331,15 +256,9 @@ exports.handle = function (event, context, callback) { '`key` VARCHAR(50) NOT NULL, ' + '`value` VARCHAR(50) NOT NULL, ' + 'PRIMARY KEY (`id`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS sponsors', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS sponsors'); connection.query('CREATE TABLE `sponsors` ( ' + '`id` INT(11) NOT NULL, ' + @@ -353,15 +272,9 @@ exports.handle = function (event, context, callback) { '`sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + 'PRIMARY KEY (`id`), ' + 'KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS sponsor_tiers', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS sponsor_tiers'); connection.query('CREATE TABLE `sponsor_tiers` ( ' + '`id` INT(11) NOT NULL, ' + @@ -372,15 +285,9 @@ exports.handle = function (event, context, callback) { '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + 'PRIMARY KEY (`id`), ' + 'KEY `ix_sponsor_tiers_name` (`name`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); - connection.query('DROP TABLE IF EXISTS users', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + connection.query('DROP TABLE IF EXISTS users'); connection.query('CREATE TABLE `users` ( ' + '`id` INT(11) NOT NULL, ' + @@ -394,17 +301,13 @@ exports.handle = function (event, context, callback) { 'PRIMARY KEY (`id`), ' + 'KEY `ix_users_email` (`email`), ' + 'KEY `ix_users_cognito_id` (`cognitoId`) ' + - ')', function (err, rows, fields) { - if (err) throw err; - console.log(rows); - }); + ')'); connection.end(); + console.log('Schema has been created.'); } - }).catch(function (err) { - console.log('this mfer errored'); /*DM: Debug */ - console.log(err); /*DM: Debug */ + callback(err); }); callback(); From 1ac4d79515bab437b7446f49f2a4324ffa8545b6 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 22 Jul 2020 15:09:57 -0500 Subject: [PATCH 014/140] GD-1627: Research/Decide/Do the migration and schema --- packages/cloudformation/templates/givesource-aurora.yml | 5 ++++- packages/lambda/src/database/createSchema/index.js | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index aa4ee7f7..7b679c4d 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -18,6 +18,9 @@ Parameters: Type: String LambdaSecurityGroupId: Type: String + Lambda: + Timeout: + Default: 120 Resources: GivesourceAuroraSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -97,7 +100,7 @@ Resources: MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" - Timeout: !Ref DefaultLambdaFunctionTimeout + Timeout: !FindInMap [Lambda, Timeout, Default] VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroupId diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index 23f1677c..87d1c825 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -15,6 +15,7 @@ */ const mysql = require("mysql"); +const response = require('cfn-response'); const Request = require('./../../aws/request'); const SecretsManager = require('./../../aws/secretsManager'); @@ -26,9 +27,7 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) }).then(function (response) { - if ('SecretString' in response) { - console.log("Connecting to Aurora"); let connection = mysql.createConnection({ host: process.env.AURORA_DB_HOST, user: process.env.DATABASE_USER, @@ -44,7 +43,6 @@ exports.handle = function (event, context, callback) { connection.query('CREATE DATABASE IF NOT EXISTS `givesource` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { if (err) throw err; - console.log(rows); }); connection.changeUser({database: 'givesource'}); @@ -307,8 +305,11 @@ exports.handle = function (event, context, callback) { console.log('Schema has been created.'); } }).catch(function (err) { + console.log(err); + response.send(event, context, response.FAILED); callback(err); }); + response.send(event, context, response.SUCCESS); callback(); }; \ No newline at end of file From 634c620ef9ba6126fb5263316b2ce2fbcea12722 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 23 Jul 2020 08:41:51 -0500 Subject: [PATCH 015/140] GD-1627: Research/Decide/Do the migration and schema --- .../templates/givesource-aurora.yml | 6 ++---- .../cloudformation/templates/givesource.yml | 1 - .../lambda/src/database/createSchema/index.js | 17 ++++++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 7b679c4d..3a5d4873 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -14,13 +14,11 @@ Parameters: Type: String DefaultLambdaFunctionTimeout: Type: Number + Default: 120 LambdaRoleArn: Type: String LambdaSecurityGroupId: Type: String - Lambda: - Timeout: - Default: 120 Resources: GivesourceAuroraSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -100,7 +98,7 @@ Resources: MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" - Timeout: !FindInMap [Lambda, Timeout, Default] + Timeout: !Ref DefaultLambdaFunctionTimeout VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroupId diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index c093ced9..0bed969b 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -106,7 +106,6 @@ Resources: Properties: Parameters: StackName: !Ref AWS::StackName - DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] LambdaRoleArn: !GetAtt RDSSchemaLambdaRole.Arn LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index 87d1c825..55a88caf 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -24,14 +24,19 @@ exports.handle = function (event, context, callback) { const secretsManager = new SecretsManager(); const request = new Request(event, context); + if (event.RequestType === 'Update' || event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS, {}); + return; + } + request.validate().then(function () { return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) - }).then(function (response) { - if ('SecretString' in response) { + }).then(function (res) { + if ('SecretString' in res) { let connection = mysql.createConnection({ host: process.env.AURORA_DB_HOST, user: process.env.DATABASE_USER, - password: JSON.parse(response.SecretString).password, + password: JSON.parse(res.SecretString).password, ssl: true, port: 3306 }); @@ -302,14 +307,12 @@ exports.handle = function (event, context, callback) { ')'); connection.end(); - console.log('Schema has been created.'); + response.send(event, context, response.SUCCESS, {}); + callback(); } }).catch(function (err) { console.log(err); response.send(event, context, response.FAILED); callback(err); }); - - response.send(event, context, response.SUCCESS); - callback(); }; \ No newline at end of file From 0c76d9f843c8c9e381916352c0befe09ab4c69b5 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 23 Jul 2020 10:50:09 -0500 Subject: [PATCH 016/140] GD-1627: Research/Decide/Do the migration and schema --- .../cloudformation/templates/givesource.yml | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 0bed969b..27dbcd82 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -302,19 +302,18 @@ Resources: - ssm:DeleteParameter - ssm:GetParameter - ssm:PutParameter - - secretsmanager:GetSecretValue Resource: '*' -# SecretsManagerManagedPolicy: -# Type: AWS::IAM::ManagedPolicy -# Properties: -# PolicyDocument: -# Version: 2012-10-17 -# Statement: -# - Effect: Allow -# Action: -# - secretsmanager:GetSecretValue -# Resource: '*' + SecretsManagerManagedPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: '*' LambdaRole: Type: AWS::IAM::Role @@ -368,7 +367,7 @@ Resources: - !Ref LambdaManagedPolicy - !Ref S3ManagedPolicy - !Ref SSMManagedPolicy - - arn:aws:iam::aws:policy/SecretsManagerReadWrite + - !Ref SecretsManagerManagedPolicy CustomStack: Type: AWS::CloudFormation::Stack From 30090684e6d2772bc36029975af60c392f658baf Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 23 Jul 2020 16:15:49 -0500 Subject: [PATCH 017/140] GD-1627: Research/Decide/Do the migration and schema --- .../cloudformation/templates/givesource-aurora.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 3a5d4873..ea953414 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -12,9 +12,6 @@ Parameters: Default: adminUser StackName: Type: String - DefaultLambdaFunctionTimeout: - Type: Number - Default: 120 LambdaRoleArn: Type: String LambdaSecurityGroupId: @@ -63,17 +60,16 @@ Resources: MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' <%={{ }}=%> - Engine: aurora + Engine: aurora-mysql EngineMode: serverless - EngineVersion: 5.6.10a + EngineVersion: 5.7.mysql_aurora.2.07.1 EnableHttpEndpoint: true ScalingConfiguration: AutoPause: true MaxCapacity: 16 MinCapacity: 1 SecondsUntilAutoPause: 900 # 15 min - DBSubnetGroupName: - Ref: DBSubnetGroup + DBSubnetGroupName: !Ref DBSubnetGroup VpcSecurityGroupIds: - !GetAtt GivesourceAuroraSecurityGroup.GroupId DependsOn: DBSecret @@ -98,7 +94,7 @@ Resources: MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" - Timeout: !Ref DefaultLambdaFunctionTimeout + Timeout: 120 #seconds VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroupId From e311d52da6bb981eeea579c6eeb7d7751e5869b7 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 27 Jul 2020 09:12:18 -0500 Subject: [PATCH 018/140] GD-1627: Research/Decide/Do the migration and schema --- .../templates/givesource-aurora.yml | 31 ++++++++++++++--- .../cloudformation/templates/givesource.yml | 33 ------------------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index ea953414..04cc3301 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -12,11 +12,33 @@ Parameters: Default: adminUser StackName: Type: String - LambdaRoleArn: - Type: String LambdaSecurityGroupId: Type: String Resources: + SecretsManagerManagedPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: '*' + CreateSchemaLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + - edgelambda.amazonaws.com + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + - !Ref SecretsManagerManagedPolicy GivesourceAuroraSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: @@ -88,11 +110,10 @@ Resources: DATABASE_SECRET_ARN: !Ref DBSecret AURORA_DB_HOST: !GetAtt RDSCluster.Endpoint.Address SECRETS_MANAGER_SECRET_ID: !Sub "${AWS::StackName}-AuroraUserSecret" - FunctionName: !Sub |- - ${StackName}-CreateSchema + FunctionName: !Sub ${StackName}-CreateSchema Handler: "index.handle" MemorySize: 128 - Role: !Ref LambdaRoleArn + Role: !GetAtt CreateSchemaLambdaRole.Arn Runtime: "nodejs12.x" Timeout: 120 #seconds VpcConfig: diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 27dbcd82..2308f345 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -106,7 +106,6 @@ Resources: Properties: Parameters: StackName: !Ref AWS::StackName - LambdaRoleArn: !GetAtt RDSSchemaLambdaRole.Arn LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 @@ -304,17 +303,6 @@ Resources: - ssm:PutParameter Resource: '*' - SecretsManagerManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - secretsmanager:GetSecretValue - Resource: '*' - LambdaRole: Type: AWS::IAM::Role Properties: @@ -348,27 +336,6 @@ Resources: - Key: Name Value: givesource-lambda - RDSSchemaLambdaRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Action: sts:AssumeRole - Principal: - Service: - - lambda.amazonaws.com - - edgelambda.amazonaws.com - ManagedPolicyArns: - - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - - !Ref ApiGatewayManagedPolicy - - !Ref CloudFormationManagedPolicy - - !Ref CloudWatchLogsManagedPolicy - - !Ref LambdaManagedPolicy - - !Ref S3ManagedPolicy - - !Ref SSMManagedPolicy - - !Ref SecretsManagerManagedPolicy - CustomStack: Type: AWS::CloudFormation::Stack Properties: From 9427a44c5e07453c4e6074b95786b500ebdc6b43 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 27 Jul 2020 09:13:07 -0500 Subject: [PATCH 019/140] GD-1627: Research/Decide/Do the migration and schema --- packages/lambda/src/database/createSchema/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index 55a88caf..dc24ea6d 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -312,7 +312,7 @@ exports.handle = function (event, context, callback) { } }).catch(function (err) { console.log(err); - response.send(event, context, response.FAILED); + response.send(event, context, response.FAILED, {}); callback(err); }); }; \ No newline at end of file From 2a8cd84fd365a990ac21550e1536c35ce6680e77 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 27 Jul 2020 13:58:50 -0500 Subject: [PATCH 020/140] GD-1627: Research/Decide/Do the migration and schema --- packages/cloudformation/templates/givesource-aurora.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 04cc3301..c56d99de 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -35,7 +35,6 @@ Resources: Principal: Service: - lambda.amazonaws.com - - edgelambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref SecretsManagerManagedPolicy From c9a4f46bd03059ae06bea540d33158f1ca88dd6f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 27 Jul 2020 14:23:16 -0500 Subject: [PATCH 021/140] GD-1627: Research/Decide/Do the migration and schema --- packages/cloudformation/templates/givesource-aurora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index c56d99de..8fac4a4b 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -24,7 +24,7 @@ Resources: - Effect: Allow Action: - secretsmanager:GetSecretValue - Resource: '*' + Resource: !Ref DBSecret CreateSchemaLambdaRole: Type: AWS::IAM::Role Properties: From 7de2b72e6a669c70fa342867f124d0e1cb79ea85 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 28 Jul 2020 08:46:41 -0500 Subject: [PATCH 022/140] GD-1627: Research/Decide/Do the migration and schema --- packages/cloudformation/templates/givesource-aurora.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 8fac4a4b..e6fde2db 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -133,6 +133,12 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-StackName + DBSecretArn: + Description: DBSecret Arn + Value: !Ref DBSecret + Export: + Name: !Sub ${AWS::StackName}-DBSecretArn + DatabaseClusterArn: Description: Aurora Cluster ARN Value: !Ref RDSCluster From 4bfa199eb4a8f766a0410696e44de0e6e1323bfb Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 28 Jul 2020 14:00:49 -0500 Subject: [PATCH 023/140] GD-1640: Update the settings repository --- packages/lambda/config/webpack.config.js | 2 +- packages/lambda/package-lock.json | 227 +++++++++++++++++- packages/lambda/package.json | 2 + .../lambda/src/database/createSchema/index.js | 26 +- 4 files changed, 240 insertions(+), 17 deletions(-) diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 1707fc43..87f6ae36 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -166,7 +166,7 @@ module.exports = { libraryTarget: 'commonjs2', }, target: 'node', - externals: {'aws-sdk': 'commonjs aws-sdk'}, + externals: {'aws-sdk': 'commonjs aws-sdk', 'sequelize': 'commonjs sequelize'}, module: { rules: [ { diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index ae5c36d5..a2224909 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -127,6 +127,11 @@ "to-fast-properties": "^2.0.0" } }, + "@types/node": { + "version": "14.0.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz", + "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==" + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -386,6 +391,16 @@ "color-convert": "^1.9.0" } }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -1013,6 +1028,15 @@ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1571,6 +1595,11 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -1618,6 +1647,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -1736,6 +1770,11 @@ "estraverse": "^4.1.1" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -2748,6 +2787,14 @@ "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg=", "dev": true }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -3053,6 +3100,11 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3382,6 +3434,11 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3795,8 +3852,7 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash.clonedeep": { "version": "4.5.0", @@ -3882,6 +3938,11 @@ "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -3901,7 +3962,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "requires": { "yallist": "^3.0.2" } @@ -4300,6 +4360,56 @@ } } }, + "mysql2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", + "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", + "requires": { + "cardinal": "^2.1.1", + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -5009,8 +5119,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { "version": "1.1.31", @@ -5176,6 +5285,14 @@ "readable-stream": "^2.0.2" } }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5313,6 +5430,14 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, "rimraf": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", @@ -5382,8 +5507,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "samsam": { "version": "1.1.2", @@ -5423,6 +5547,74 @@ "upper-case-first": "^1.1.2" } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.3.tgz", + "integrity": "sha512-WO/b1ehjSFKlBCHzwZoaPhoW3WyXXy9x74yPrOP8NpE67wzbv0dIucDO4a+THLVyl3lnv3nFMZdJRdkUgb/ZAw==", + "requires": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", + "toposort-class": "^1.0.1", + "uuid": "^8.1.0", + "validator": "^10.11.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "uuid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" + } + } + }, + "sequelize-pool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -6228,6 +6420,11 @@ "repeat-string": "^1.6.1" } }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -6500,6 +6697,11 @@ "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.10.0.tgz", "integrity": "sha1-DZcBTX4Zy+ikeAx5L2C1BaQwev0=" }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -6636,6 +6838,14 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6719,8 +6929,7 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" }, "yargs": { "version": "12.0.5", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 3bc06253..5aecd093 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -24,7 +24,9 @@ "json-loader": "^0.5.7", "mime": "^2.2.2", "mysql": "^2.18.1", + "mysql2": "^2.1.0", "rimraf": "^2.6.1", + "sequelize": "^6.3.3", "validate.js": "0.10.0" }, "devDependencies": { diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index dc24ea6d..ce1033ab 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -18,19 +18,31 @@ const mysql = require("mysql"); const response = require('cfn-response'); const Request = require('./../../aws/request'); const SecretsManager = require('./../../aws/secretsManager'); +const Sequelize = require('sequelize'); +const mysql2 = require('mysql2'); exports.handle = function (event, context, callback) { console.log(JSON.stringify(event)); const secretsManager = new SecretsManager(); const request = new Request(event, context); - if (event.RequestType === 'Update' || event.RequestType === 'Delete') { - response.send(event, context, response.SUCCESS, {}); - return; - } - - request.validate().then(function () { - return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) + // if (event.RequestType === 'Update' || event.RequestType === 'Delete') { + // response.send(event, context, response.SUCCESS, {}); + // return; + // } + + request.validate().then(function (res) { + console.log('right above sequelize'); /*DM: Debug */ + const sequelize = new Sequelize('givesource', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { + host: process.env.AURORA_DB_HOST, + dialect: "mysql", + dialectModule: mysql2, + }); + console.log('hit here'); /*DM: Debug */ + return sequelize.authenticate(); + }).then(function (sequelize) { + console.log(sequelize); /*DM: Debug */ + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID); }).then(function (res) { if ('SecretString' in res) { let connection = mysql.createConnection({ From a3f1aeabcc09e7edc8526c78f1969dad74f1bebb Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 28 Jul 2020 16:16:55 -0500 Subject: [PATCH 024/140] WIP --- packages/lambda/config/webpack.config.js | 4 +- packages/lambda/package-lock.json | 69 +++++-------------- packages/lambda/package.json | 2 +- .../lambda/src/database/createSchema/index.js | 12 ++-- 4 files changed, 27 insertions(+), 60 deletions(-) diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 87f6ae36..73a5d5e8 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -166,7 +166,7 @@ module.exports = { libraryTarget: 'commonjs2', }, target: 'node', - externals: {'aws-sdk': 'commonjs aws-sdk', 'sequelize': 'commonjs sequelize'}, + externals: {'aws-sdk': 'commonjs aws-sdk'}, module: { rules: [ { @@ -186,4 +186,4 @@ module.exports = { resolve: { modules: [path.resolve(__dirname, '../src'), 'node_modules'] } -}; \ No newline at end of file +}; diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index a2224909..0f602088 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -718,11 +718,6 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, - "bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" - }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -1397,7 +1392,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cp-file": { "version": "6.2.0", @@ -4315,51 +4311,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "requires": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "mysql2": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", @@ -5071,6 +5022,14 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pg-hstore": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", + "integrity": "sha512-qpeTpdkguFgfdoidtfeTho1Q1zPVPbtMHgs8eQ+Aan05iLmIs3Z3oo5DOZRclPGoQ4i68I1kCtQSJSa7i0ZVYg==", + "requires": { + "underscore": "^1.7.0" + } + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -6513,6 +6472,11 @@ } } }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + }, "unicode": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/unicode/-/unicode-11.0.1.tgz", @@ -6668,7 +6632,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "uuid-validate": { "version": "0.0.2", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 5aecd093..79131c6d 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -23,7 +23,7 @@ "dotenv": "^4.0.0", "json-loader": "^0.5.7", "mime": "^2.2.2", - "mysql": "^2.18.1", + "pg-hstore": "^2.3.3", "mysql2": "^2.1.0", "rimraf": "^2.6.1", "sequelize": "^6.3.3", diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index ce1033ab..d96b8701 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const mysql = require("mysql"); const response = require('cfn-response'); const Request = require('./../../aws/request'); const SecretsManager = require('./../../aws/secretsManager'); @@ -33,10 +32,13 @@ exports.handle = function (event, context, callback) { request.validate().then(function (res) { console.log('right above sequelize'); /*DM: Debug */ - const sequelize = new Sequelize('givesource', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { + const sequelize = new Sequelize({ host: process.env.AURORA_DB_HOST, - dialect: "mysql", - dialectModule: mysql2, + username: process.env.DATABASE_USER, + password: JSON.parse(res.SecretString).password, + database: 'givesource', + dialect: 'mysql', + dialectModule: mysql2 }); console.log('hit here'); /*DM: Debug */ return sequelize.authenticate(); @@ -327,4 +329,4 @@ exports.handle = function (event, context, callback) { response.send(event, context, response.FAILED, {}); callback(err); }); -}; \ No newline at end of file +}; From b1499bd8411469270ed48e041e6e487b44dcbed6 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 29 Jul 2020 12:31:00 -0500 Subject: [PATCH 025/140] GD-1640: Update the settings repository --- packages/lambda/package-lock.json | 109 ++++++- packages/lambda/package.json | 3 +- .../lambda/src/database/createSchema/index.js | 297 +----------------- 3 files changed, 116 insertions(+), 293 deletions(-) diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index 0f602088..3a0d0915 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -912,6 +912,11 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -4859,6 +4864,11 @@ } } }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", @@ -5022,6 +5032,33 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pg": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.0.tgz", + "integrity": "sha512-jQPKWHWxbI09s/Z9aUvoTbvGgoj98AU7FDCcQ7kdejupn/TcNpx56v2gaOTzXkzOajmOEJEdi9eTh9cA2RVAjQ==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.3.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.5", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + } + } + }, + "pg-connection-string": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" + }, "pg-hstore": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", @@ -5030,6 +5067,41 @@ "underscore": "^1.7.0" } }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", + "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" + }, + "pg-protocol": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", + "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "^1.0.0" + } + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -5051,6 +5123,29 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz", + "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5906,6 +6001,14 @@ "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6252,8 +6355,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", @@ -6882,8 +6984,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "4.0.0", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 79131c6d..fba84c0c 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -23,8 +23,9 @@ "dotenv": "^4.0.0", "json-loader": "^0.5.7", "mime": "^2.2.2", - "pg-hstore": "^2.3.3", "mysql2": "^2.1.0", + "pg": "^8.3.0", + "pg-hstore": "^2.3.3", "rimraf": "^2.6.1", "sequelize": "^6.3.3", "validate.js": "0.10.0" diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index d96b8701..037ec0eb 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -30,300 +30,21 @@ exports.handle = function (event, context, callback) { // return; // } - request.validate().then(function (res) { + request.validate().then(function () { + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID); + }).then(function (res) { console.log('right above sequelize'); /*DM: Debug */ - const sequelize = new Sequelize({ + const sequelize = new Sequelize('givesource', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { host: process.env.AURORA_DB_HOST, - username: process.env.DATABASE_USER, - password: JSON.parse(res.SecretString).password, - database: 'givesource', dialect: 'mysql', - dialectModule: mysql2 + dialectModule: mysql2, + port: 3306 }); - console.log('hit here'); /*DM: Debug */ return sequelize.authenticate(); - }).then(function (sequelize) { - console.log(sequelize); /*DM: Debug */ - return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID); }).then(function (res) { - if ('SecretString' in res) { - let connection = mysql.createConnection({ - host: process.env.AURORA_DB_HOST, - user: process.env.DATABASE_USER, - password: JSON.parse(res.SecretString).password, - ssl: true, - port: 3306 - }); - - connection.connect(function (err) { - if (err) throw err; - console.log('connected!'); /*DM: Debug */ - }); - - connection.query('CREATE DATABASE IF NOT EXISTS `givesource` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { - if (err) throw err; - }); - - connection.changeUser({database: 'givesource'}); - - //create the database - connection.query('DROP TABLE IF EXISTS contents'); - - connection.query( - 'CREATE TABLE `contents` (' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`parentId` INT(11) NOT NULL DEFAULT 0, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_contents_parent_id_index` (`parentId`))'); - - connection.query('DROP TABLE IF EXISTS donations'); - - connection.query('CREATE TABLE `donations` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - '`count` INT(11) NOT NULL DEFAULT 0, ' + - '`fees` INT(11) NOT NULL DEFAULT 0, ' + - '`isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - '`paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + - '`subtotal` INT(11) NOT NULL DEFAULT 0, ' + - '`subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + - '`total` INT(11) NOT NULL DEFAULT 0, ' + - '`type` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`donorId` INT(11) NOT NULL DEFAULT 0, ' + - '`note` VARCHAR(255) DEFAULT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + - 'KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + - 'KEY `ix_donations_donor_id` (`donorId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS donors'); - - connection.query('CREATE TABLE `donors` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - '`address1` VARCHAR(50) NOT NULL, ' + - '`address2` VARCHAR(50) NOT NULL, ' + - '`city` VARCHAR(50) NOT NULL, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`state` VARCHAR(50) NOT NULL, ' + - '`zip` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_donors_email` (`email`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS files'); - - connection.query('CREATE TABLE `files` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`path` VARCHAR(50) NOT NULL, ' + - '`filename` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS messages'); - - connection.query('CREATE TABLE `messages` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`message` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS metrics'); - - connection.query('CREATE TABLE `metrics` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`key` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers'); - - connection.query('CREATE TABLE `nonprofit_donation_tiers` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`amount` INT(11) NOT NULL DEFAULT 0, ' + - '`description` VARCHAR(255) NOT NULL, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofits'); - - connection.query('CREATE TABLE `nonprofits` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`address1` VARCHAR(50) NOT NULL, ' + - '`address2` VARCHAR(50) NOT NULL, ' + - '`category1` INT(11) NOT NULL DEFAULT 0, ' + - '`category2` INT(11) NOT NULL DEFAULT 0, ' + - '`category3` INT(11) NOT NULL DEFAULT 0, ' + - '`city` VARCHAR(50) NOT NULL, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`state` VARCHAR(50) NOT NULL, ' + - '`zip` VARCHAR(50) NOT NULL, ' + - '`legalName` VARCHAR(50) NOT NULL, ' + - '`legalNameSearch` VARCHAR(50) NOT NULL, ' + - '`logoFileId` INT(11) NOT NULL DEFAULT 0, ' + - '`longDescription` VARCHAR(255) NOT NULL, ' + - '`receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`shortDescription` VARCHAR(50) NOT NULL, ' + - '`slug` VARCHAR(50) NOT NULL, ' + - '`socialSharingDescription` VARCHAR(50) NOT NULL, ' + - '`socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + - '`status` VARCHAR(50) NOT NULL, ' + - '`taxId` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + - 'KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + - 'KEY `ix_nonprofits_slug` (`slug`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofit_slides'); - - connection.query('CREATE TABLE `nonprofit_slides` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`caption` VARCHAR(50) NOT NULL, ' + - '`embedUrl` VARCHAR(50) NOT NULL, ' + - '`externalId` VARCHAR(50) NOT NULL, ' + - '`thumbnail` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`url` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS payment_transactions'); - - connection.query('CREATE TABLE `payment_transactions` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`billingZip` VARCHAR(50) NOT NULL, ' + - '`creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + - '`creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + - '`creditCardLast4` VARCHAR(50) NOT NULL, ' + - '`creditCardName` VARCHAR(50) NOT NULL, ' + - '`creditCardType` VARCHAR(50) NOT NULL, ' + - '`isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + - '`transactionId` VARCHAR(50) NOT NULL, ' + - '`transactionStatus` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS reports'); - - connection.query('CREATE TABLE `reports` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`status` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS settings'); - - connection.query('CREATE TABLE `settings` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`key` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS sponsors'); - - connection.query('CREATE TABLE `sponsors` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`logoUrl` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`url` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS sponsor_tiers'); - - connection.query('CREATE TABLE `sponsor_tiers` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`size` VARCHAR(50) NOT NULL, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_sponsor_tiers_name` (`name`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS users'); - - connection.query('CREATE TABLE `users` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`cognitoId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_users_email` (`email`), ' + - 'KEY `ix_users_cognito_id` (`cognitoId`) ' + - ')'); - connection.end(); - - response.send(event, context, response.SUCCESS, {}); - callback(); - } + console.log(res); /*DM: Debug */ + response.send(event, context, response.SUCCESS, {}); + callback(); }).catch(function (err) { console.log(err); response.send(event, context, response.FAILED, {}); From 12fad16f702f73ce54ef2b44f14f7749ae8c1951 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 29 Jul 2020 16:33:35 -0500 Subject: [PATCH 026/140] GD-1640: Update the settings repository --- packages/lambda/.gitignore | 5 +- .../20200729184046-create-setting.js | 35 ++ packages/lambda/models/index.js | 37 ++ packages/lambda/models/setting.js | 24 ++ packages/lambda/package-lock.json | 407 ++++++++++++++++++ packages/lambda/package.json | 1 + .../lambda/src/database/createSchema/index.js | 21 +- 7 files changed, 521 insertions(+), 9 deletions(-) create mode 100644 packages/lambda/migrations/20200729184046-create-setting.js create mode 100644 packages/lambda/models/index.js create mode 100644 packages/lambda/models/setting.js diff --git a/packages/lambda/.gitignore b/packages/lambda/.gitignore index 7d42b7ed..b3d32a58 100644 --- a/packages/lambda/.gitignore +++ b/packages/lambda/.gitignore @@ -13,4 +13,7 @@ dist/ clean # Ignore build directory -build/ \ No newline at end of file +build/ + +# Ignore config json +config/config.json \ No newline at end of file diff --git a/packages/lambda/migrations/20200729184046-create-setting.js b/packages/lambda/migrations/20200729184046-create-setting.js new file mode 100644 index 00000000..f75abd6b --- /dev/null +++ b/packages/lambda/migrations/20200729184046-create-setting.js @@ -0,0 +1,35 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Settings', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + key: { + type: Sequelize.STRING + }, + value: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + isDeleted: { + type: Sequelize.BOOLEAN, + defaultValue: false, + allowNull: false + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Settings'); + } +}; \ No newline at end of file diff --git a/packages/lambda/models/index.js b/packages/lambda/models/index.js new file mode 100644 index 00000000..33f09e77 --- /dev/null +++ b/packages/lambda/models/index.js @@ -0,0 +1,37 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../config/config.json')[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/packages/lambda/models/setting.js b/packages/lambda/models/setting.js new file mode 100644 index 00000000..5452ebf8 --- /dev/null +++ b/packages/lambda/models/setting.js @@ -0,0 +1,24 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Setting extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + Setting.init({ + key: DataTypes.STRING, + value: DataTypes.STRING + }, { + sequelize, + modelName: 'Setting', + }); + return Setting; +}; \ No newline at end of file diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index 3a0d0915..bf4c6e60 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -320,6 +320,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", @@ -1179,6 +1185,20 @@ } } }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1340,6 +1360,16 @@ } } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -1504,6 +1534,16 @@ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1684,6 +1724,42 @@ "safe-buffer": "^5.0.1" } }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -1749,12 +1825,56 @@ "is-arrayish": "^0.2.1" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1797,6 +1917,16 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -1862,6 +1992,23 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2208,6 +2355,17 @@ "readable-stream": "^2.0.0" } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -3120,6 +3278,12 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, "inquirer": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz", @@ -3629,6 +3793,41 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, + "js-beautify": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.11.0.tgz", + "integrity": "sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A==", + "dev": true, + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "~1.0.3", + "nopt": "^4.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -3717,6 +3916,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonwebtoken": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", @@ -3967,6 +4175,15 @@ "yallist": "^3.0.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4037,6 +4254,22 @@ "p-is-promise": "^1.1.0" } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -4410,6 +4643,12 @@ "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4489,6 +4728,16 @@ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -4802,6 +5051,16 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -5164,6 +5423,12 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -5664,6 +5929,111 @@ } } }, + "sequelize-cli": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", + "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", + "dev": true, + "requires": { + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.3.0", + "yargs": "^13.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -5729,6 +6099,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6408,6 +6784,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "title-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", @@ -6543,6 +6929,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-detect": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", @@ -6574,6 +6966,15 @@ } } }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "requires": { + "bluebird": "^3.7.2" + } + }, "underscore": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", @@ -6615,6 +7016,12 @@ "imurmurhash": "^0.1.4" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index fba84c0c..8d240d5b 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -60,6 +60,7 @@ "randomstring": "^1.1.5", "raw-loader": "^0.5.1", "request": "^2.88.0", + "sequelize-cli": "^6.2.0", "sinon": "^2.3.6", "slug": "^0.9.3", "uuid-validate": "0.0.2", diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js index 037ec0eb..0ca0eba4 100644 --- a/packages/lambda/src/database/createSchema/index.js +++ b/packages/lambda/src/database/createSchema/index.js @@ -25,22 +25,27 @@ exports.handle = function (event, context, callback) { const secretsManager = new SecretsManager(); const request = new Request(event, context); - // if (event.RequestType === 'Update' || event.RequestType === 'Delete') { - // response.send(event, context, response.SUCCESS, {}); - // return; - // } + if (event.RequestType === 'Update' || event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS, {}); + return; + } request.validate().then(function () { return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID); }).then(function (res) { - console.log('right above sequelize'); /*DM: Debug */ - const sequelize = new Sequelize('givesource', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { + const sequelize = new Sequelize('', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { host: process.env.AURORA_DB_HOST, dialect: 'mysql', dialectModule: mysql2, - port: 3306 + port: 3306, + dialectOptions: { + ssl: { + rejectUnauthorized: false + } + } }); - return sequelize.authenticate(); + + return sequelize.query("CREATE DATABASE IF NOT EXIST 'givesource' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;"); }).then(function (res) { console.log(res); /*DM: Debug */ response.send(event, context, response.SUCCESS, {}); From f7e3994d0ba092d49576ed654578d4137b08d59f Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 31 Jul 2020 10:07:57 -0500 Subject: [PATCH 027/140] [GD-1627] Research/Decide/Do the migration and schema * Created initial aurora cloudformation * Added code to bootstrap hardcoded schema --- cloudformation/vpc.yml | 177 +++++++++- .../templates/givesource-aurora.yml | 104 +++++- .../cloudformation/templates/givesource.yml | 12 + packages/lambda/config/webpack.config.js | 3 + packages/lambda/package-lock.json | 61 +++- packages/lambda/package.json | 1 + packages/lambda/src/aws/secretsManager.js | 39 +++ .../lambda/src/database/createSchema/index.js | 318 ++++++++++++++++++ 8 files changed, 696 insertions(+), 19 deletions(-) create mode 100644 packages/lambda/src/aws/secretsManager.js create mode 100644 packages/lambda/src/database/createSchema/index.js diff --git a/cloudformation/vpc.yml b/cloudformation/vpc.yml index 88fe50a8..99ac285f 100644 --- a/cloudformation/vpc.yml +++ b/cloudformation/vpc.yml @@ -129,17 +129,176 @@ Resources: - Key: SubnetType Value: Public - Key: Name - Value: secondary-givesource + Value: secondary-public-givesource - billingDashboard: + primaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + primaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt primaryPrivateEip.AllocationId + SubnetId: !Ref primaryPublicSubnet + + primaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: primary-private-givesource + + primaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref primaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref primaryPrivateNatGateway + + primaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.10.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [0, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: primary-private-givesource + + primaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref primaryPrivateSubnet + RouteTableId: !Ref primaryPrivateRouteTable + + secondaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + secondaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt secondaryPrivateEip.AllocationId + SubnetId: !Ref secondaryPublicSubnet + + secondaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref secondaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref secondaryPrivateNatGateway + + secondaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.12.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [1, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref secondaryPrivateSubnet + RouteTableId: !Ref secondaryPrivateRouteTable + + vpcDashboard: Type: AWS::CloudWatch::Dashboard Properties: - DashboardName: !Sub givesource-billing-${AWS::Region} + DashboardName: !Sub givesource-vpc-${AWS::Region} DashboardBody: !Sub - > { "start": "-P6M", "widgets": [ + { + "type": "metric", + "x": 0, + "y": 0, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromSource", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromSource", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "period": 300, + "title": "NAT Gateway Bytes received from clients in your VPC" + } + }, + { + "type": "metric", + "x": 0, + "y": 6, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromDestination", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromDestination", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "title": "NAT Gateway Bytes received from the destination" + } + }, { "type": "metric", "x": 0, @@ -211,3 +370,15 @@ Outputs: Export: Name: givesource-secondary-public-subnet + primaryPrivateSubnet: + Description: Primary Private Subnet for Givesource + Value: !Ref primaryPrivateSubnet + Export: + Name: givsource-primary-private-subnet + + secondaryPrivateSubnet: + Description: Secondary Private Subnet for Givesource + Value: !Ref secondaryPrivateSubnet + Export: + Name: givesource-secondary-private-subnet + diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 605815d4..e6fde2db 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -10,21 +10,60 @@ Parameters: MinLength: '1' Type: String Default: adminUser - DBSubnetList: - Description: "List of subnets for the Aurora RDS cluster" - Type: List - ConstraintDescription: "must be a list of at least two existing subnets associated with at least two different availability zones." - Default: "subnet-ea69d68e,subnet-e01c0fcc" StackName: Type: String + LambdaSecurityGroupId: + Type: String Resources: + SecretsManagerManagedPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: !Ref DBSecret + CreateSchemaLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + - !Ref SecretsManagerManagedPolicy + GivesourceAuroraSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for aurora + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-aurora + LambdaAuroraIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: allows access from lambda into aurora + GroupId: !GetAtt GivesourceAuroraSecurityGroup.GroupId + IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupId: !Ref LambdaSecurityGroupId DBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: CloudFormation managed DB subnet group. SubnetIds: - - !Select [0, !Ref DBSubnetList ] - - !Select [1, !Ref DBSubnetList ] + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DBSecret: Type: AWS::SecretsManager::Secret Properties: @@ -42,16 +81,51 @@ Resources: MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' <%={{ }}=%> - Engine: aurora + Engine: aurora-mysql EngineMode: serverless - EngineVersion: 5.6.10a + EngineVersion: 5.7.mysql_aurora.2.07.1 + EnableHttpEndpoint: true ScalingConfiguration: AutoPause: true MaxCapacity: 16 MinCapacity: 1 SecondsUntilAutoPause: 900 # 15 min - DBSubnetGroupName: - Ref: DBSubnetGroup + DBSubnetGroupName: !Ref DBSubnetGroup + VpcSecurityGroupIds: + - !GetAtt GivesourceAuroraSecurityGroup.GroupId + DependsOn: DBSecret + CreateSchemaLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/CreateSchema.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref AWS::StackName + DATABASE_USER: !Ref DBMasterUserName + DATABASE_SECRET_ARN: !Ref DBSecret + AURORA_DB_HOST: !GetAtt RDSCluster.Endpoint.Address + SECRETS_MANAGER_SECRET_ID: !Sub "${AWS::StackName}-AuroraUserSecret" + FunctionName: !Sub ${StackName}-CreateSchema + Handler: "index.handle" + MemorySize: 128 + Role: !GetAtt CreateSchemaLambdaRole.Arn + Runtime: "nodejs12.x" + Timeout: 120 #seconds + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + DependsOn: RDSCluster + CreateSchemaLambdaCustomResource: + Type: "Custom::CreateSchemaLambdaInvoker" + Properties: + ServiceToken: !GetAtt CreateSchemaLambdaFunction.Arn Outputs: StackName: Description: Aurora Stack Name @@ -59,6 +133,12 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-StackName + DBSecretArn: + Description: DBSecret Arn + Value: !Ref DBSecret + Export: + Name: !Sub ${AWS::StackName}-DBSecretArn + DatabaseClusterArn: Description: Aurora Cluster ARN Value: !Ref RDSCluster @@ -87,4 +167,4 @@ Outputs: Description: Aurora Database User Value: !Ref DBMasterUserName Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName \ No newline at end of file + Name: !Sub ${AWS::StackName}-DatabaseMasterUserName diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index bf358b99..2308f345 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -106,6 +106,7 @@ Resources: Properties: Parameters: StackName: !Ref AWS::StackName + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 @@ -324,6 +325,17 @@ Resources: - !Ref SESManagedPolicy - !Ref SSMManagedPolicy + LambdaSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for lambda + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-lambda + CustomStack: Type: AWS::CloudFormation::Stack Properties: diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 885f185a..1707fc43 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -155,6 +155,9 @@ module.exports = { SendDonationNotificationEmail: './src/custom/sendDonationNotificationEmail/index.js', SendDonationsReceiptEmail: './src/custom/sendDonationsReceiptEmail/index.js', SendRegistrationPendingEmail: './src/custom/sendRegistrationPendingEmail/index.js', + + // Database Lambda Functions + CreateSchema: './src/database/createSchema/index.js', }, output: { filename: '[name]/index.js', diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index 290e74e6..ae5c36d5 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -703,6 +703,11 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -1368,8 +1373,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cp-file": { "version": "6.2.0", @@ -4251,6 +4255,51 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -5715,6 +5764,11 @@ "extend-shallow": "^3.0.0" } }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -6417,8 +6471,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid-validate": { "version": "0.0.2", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index fa4191e7..3bc06253 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -23,6 +23,7 @@ "dotenv": "^4.0.0", "json-loader": "^0.5.7", "mime": "^2.2.2", + "mysql": "^2.18.1", "rimraf": "^2.6.1", "validate.js": "0.10.0" }, diff --git a/packages/lambda/src/aws/secretsManager.js b/packages/lambda/src/aws/secretsManager.js new file mode 100644 index 00000000..cddd0bea --- /dev/null +++ b/packages/lambda/src/aws/secretsManager.js @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const AWS = require('aws-sdk'); + +/** + * Secrets Manager constructor + * + * @constructor + */ +function SecretsManager() { +} + +/** + * Get a secret value from the secrets manager + * + * @param region + * @param secretId + * @returns {Promise} + */ +SecretsManager.prototype.getSecretValue = (region, secretId) => { + const secretManger = new AWS.SecretsManager({region: region}); + return secretManger.getSecretValue({SecretId: secretId}).promise(); +}; + +module.exports = SecretsManager; \ No newline at end of file diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js new file mode 100644 index 00000000..dc24ea6d --- /dev/null +++ b/packages/lambda/src/database/createSchema/index.js @@ -0,0 +1,318 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const mysql = require("mysql"); +const response = require('cfn-response'); +const Request = require('./../../aws/request'); +const SecretsManager = require('./../../aws/secretsManager'); + +exports.handle = function (event, context, callback) { + console.log(JSON.stringify(event)); + const secretsManager = new SecretsManager(); + const request = new Request(event, context); + + if (event.RequestType === 'Update' || event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS, {}); + return; + } + + request.validate().then(function () { + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) + }).then(function (res) { + if ('SecretString' in res) { + let connection = mysql.createConnection({ + host: process.env.AURORA_DB_HOST, + user: process.env.DATABASE_USER, + password: JSON.parse(res.SecretString).password, + ssl: true, + port: 3306 + }); + + connection.connect(function (err) { + if (err) throw err; + console.log('connected!'); /*DM: Debug */ + }); + + connection.query('CREATE DATABASE IF NOT EXISTS `givesource` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { + if (err) throw err; + }); + + connection.changeUser({database: 'givesource'}); + + //create the database + connection.query('DROP TABLE IF EXISTS contents'); + + connection.query( + 'CREATE TABLE `contents` (' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`parentId` INT(11) NOT NULL DEFAULT 0, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_contents_parent_id_index` (`parentId`))'); + + connection.query('DROP TABLE IF EXISTS donations'); + + connection.query('CREATE TABLE `donations` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + '`count` INT(11) NOT NULL DEFAULT 0, ' + + '`fees` INT(11) NOT NULL DEFAULT 0, ' + + '`isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + '`paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + + '`subtotal` INT(11) NOT NULL DEFAULT 0, ' + + '`subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + + '`total` INT(11) NOT NULL DEFAULT 0, ' + + '`type` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`donorId` INT(11) NOT NULL DEFAULT 0, ' + + '`note` VARCHAR(255) DEFAULT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + + 'KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + + 'KEY `ix_donations_donor_id` (`donorId`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS donors'); + + connection.query('CREATE TABLE `donors` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + '`address1` VARCHAR(50) NOT NULL, ' + + '`address2` VARCHAR(50) NOT NULL, ' + + '`city` VARCHAR(50) NOT NULL, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`state` VARCHAR(50) NOT NULL, ' + + '`zip` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_donors_email` (`email`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS files'); + + connection.query('CREATE TABLE `files` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`path` VARCHAR(50) NOT NULL, ' + + '`filename` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS messages'); + + connection.query('CREATE TABLE `messages` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`message` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS metrics'); + + connection.query('CREATE TABLE `metrics` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`key` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers'); + + connection.query('CREATE TABLE `nonprofit_donation_tiers` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`amount` INT(11) NOT NULL DEFAULT 0, ' + + '`description` VARCHAR(255) NOT NULL, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS nonprofits'); + + connection.query('CREATE TABLE `nonprofits` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`address1` VARCHAR(50) NOT NULL, ' + + '`address2` VARCHAR(50) NOT NULL, ' + + '`category1` INT(11) NOT NULL DEFAULT 0, ' + + '`category2` INT(11) NOT NULL DEFAULT 0, ' + + '`category3` INT(11) NOT NULL DEFAULT 0, ' + + '`city` VARCHAR(50) NOT NULL, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`phone` VARCHAR(50) NOT NULL, ' + + '`state` VARCHAR(50) NOT NULL, ' + + '`zip` VARCHAR(50) NOT NULL, ' + + '`legalName` VARCHAR(50) NOT NULL, ' + + '`legalNameSearch` VARCHAR(50) NOT NULL, ' + + '`logoFileId` INT(11) NOT NULL DEFAULT 0, ' + + '`longDescription` VARCHAR(255) NOT NULL, ' + + '`receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`shortDescription` VARCHAR(50) NOT NULL, ' + + '`slug` VARCHAR(50) NOT NULL, ' + + '`socialSharingDescription` VARCHAR(50) NOT NULL, ' + + '`socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + + '`status` VARCHAR(50) NOT NULL, ' + + '`taxId` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + + 'KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + + 'KEY `ix_nonprofits_slug` (`slug`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS nonprofit_slides'); + + connection.query('CREATE TABLE `nonprofit_slides` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`caption` VARCHAR(50) NOT NULL, ' + + '`embedUrl` VARCHAR(50) NOT NULL, ' + + '`externalId` VARCHAR(50) NOT NULL, ' + + '`thumbnail` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`url` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS payment_transactions'); + + connection.query('CREATE TABLE `payment_transactions` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`billingZip` VARCHAR(50) NOT NULL, ' + + '`creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + + '`creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + + '`creditCardLast4` VARCHAR(50) NOT NULL, ' + + '`creditCardName` VARCHAR(50) NOT NULL, ' + + '`creditCardType` VARCHAR(50) NOT NULL, ' + + '`isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + + '`transactionId` VARCHAR(50) NOT NULL, ' + + '`transactionStatus` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS reports'); + + connection.query('CREATE TABLE `reports` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`status` VARCHAR(50) NOT NULL, ' + + '`type` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS settings'); + + connection.query('CREATE TABLE `settings` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`key` VARCHAR(50) NOT NULL, ' + + '`value` VARCHAR(50) NOT NULL, ' + + 'PRIMARY KEY (`id`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS sponsors'); + + connection.query('CREATE TABLE `sponsors` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`logoUrl` VARCHAR(50) NOT NULL, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + '`url` VARCHAR(50) NOT NULL, ' + + '`fileId` INT(11) NOT NULL DEFAULT 0, ' + + '`sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS sponsor_tiers'); + + connection.query('CREATE TABLE `sponsor_tiers` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`name` VARCHAR(50) NOT NULL, ' + + '`size` VARCHAR(50) NOT NULL, ' + + '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_sponsor_tiers_name` (`name`) ' + + ')'); + + connection.query('DROP TABLE IF EXISTS users'); + + connection.query('CREATE TABLE `users` ( ' + + '`id` INT(11) NOT NULL, ' + + '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + '`email` VARCHAR(50) NOT NULL, ' + + '`lastName` VARCHAR(50) NOT NULL, ' + + '`firstName` VARCHAR(50) NOT NULL, ' + + '`cognitoId` INT(11) NOT NULL DEFAULT 0, ' + + '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + 'PRIMARY KEY (`id`), ' + + 'KEY `ix_users_email` (`email`), ' + + 'KEY `ix_users_cognito_id` (`cognitoId`) ' + + ')'); + connection.end(); + + response.send(event, context, response.SUCCESS, {}); + callback(); + } + }).catch(function (err) { + console.log(err); + response.send(event, context, response.FAILED, {}); + callback(err); + }); +}; \ No newline at end of file From 37140dfee31b747dda848d60f470988aa6e2911c Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 6 Aug 2020 14:21:59 -0500 Subject: [PATCH 028/140] Merged GD-1639 --- .../templates/givesource-aurora.yml | 313 ++++++--- .../cloudformation/templates/givesource.yml | 3 +- packages/lambda/bin/release.js | 24 +- packages/lambda/config/webpack.config.js | 3 +- packages/lambda/migrations/00_initial.js | 75 +++ .../20200729184046-create-setting.js | 35 - packages/lambda/package-lock.json | 600 ++++-------------- packages/lambda/package.json | 2 +- packages/lambda/src/aws/s3.js | 35 +- .../src/database/bootstrapDatabase/index.js | 83 +++ .../lambda/src/database/createSchema/index.js | 58 -- .../src/database/migrateDatabase/index.js | 95 +++ 12 files changed, 675 insertions(+), 651 deletions(-) create mode 100644 packages/lambda/migrations/00_initial.js delete mode 100644 packages/lambda/migrations/20200729184046-create-setting.js create mode 100644 packages/lambda/src/database/bootstrapDatabase/index.js delete mode 100644 packages/lambda/src/database/createSchema/index.js create mode 100644 packages/lambda/src/database/migrateDatabase/index.js diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index e6fde2db..fb453ef5 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -2,43 +2,47 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS Aurora resources for Givesource(R) Parameters: - DBMasterUserName: + DatabaseAdminUser: AllowedPattern: "[a-zA-Z0-9_]+" ConstraintDescription: must be between 1 to 16 alphanumeric characters. Description: The database admin account user name, between 1 to 16 alphanumeric characters. MaxLength: '16' MinLength: '1' Type: String - Default: adminUser + Default: admin + DatabaseMaintenanceUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database maintenance account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: maintenance + DatabaseReadwriteUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readwrite account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readwrite + DatabaseReadonlyUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readonly account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readonly + DatabaseName: + Type: String + Default: givesource StackName: Type: String LambdaSecurityGroupId: Type: String Resources: - SecretsManagerManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - secretsmanager:GetSecretValue - Resource: !Ref DBSecret - CreateSchemaLambdaRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Action: sts:AssumeRole - Principal: - Service: - - lambda.amazonaws.com - ManagedPolicyArns: - - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - - !Ref SecretsManagerManagedPolicy - GivesourceAuroraSecurityGroup: + DBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Ingress/egress rules for aurora @@ -48,15 +52,6 @@ Resources: Tags: - Key: Name Value: givesource-aurora - LambdaAuroraIngress: - Type: AWS::EC2::SecurityGroupIngress - Properties: - Description: allows access from lambda into aurora - GroupId: !GetAtt GivesourceAuroraSecurityGroup.GroupId - IpProtocol: tcp - FromPort: 3306 - ToPort: 3306 - SourceSecurityGroupId: !Ref LambdaSecurityGroupId DBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: @@ -64,22 +59,76 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DBSecret: + AdminUserSecret: Type: AWS::SecretsManager::Secret Properties: - Name: !Sub "${AWS::StackName}-AuroraUserSecret" - Description: RDS database auto-generated user password + Name: !Sub ${AWS::StackName}-AdminUserSecret + Description: Givesource database auto-generated admin user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}' - GenerateStringKey: "password" - PasswordLength: 30 + SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}"}' + GenerateStringKey: password + PasswordLength: 32 ExcludeCharacters: '"@/\' + AdminUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref AdminUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + MaintenanceUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-MaintenanceUserSecret + Description: Givesource database auto-generated maintenance user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludePunctuation: true + MaintenanceUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref MaintenanceUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + ReadwriteUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-ReadwriteUserSecret + Description: Givesource database auto-generated readwrite user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludePunctuation: true + ReadwriteUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadwriteUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + ReadonlyUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-ReadonlyUserSecret + Description: Givesource database auto-generated readonly user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludePunctuation: true + ReadonlyUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadonlyUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster RDSCluster: Type: AWS::RDS::DBCluster Properties: {{=<% %>=}} - MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' - MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' + MasterUsername: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:username}}' + MasterUserPassword: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:password}}' <%={{ }}=%> Engine: aurora-mysql EngineMode: serverless @@ -89,32 +138,69 @@ Resources: AutoPause: true MaxCapacity: 16 MinCapacity: 1 - SecondsUntilAutoPause: 900 # 15 min + SecondsUntilAutoPause: 900 DBSubnetGroupName: !Ref DBSubnetGroup VpcSecurityGroupIds: - - !GetAtt GivesourceAuroraSecurityGroup.GroupId - DependsOn: DBSecret - CreateSchemaLambdaFunction: + - !GetAtt DBSecurityGroup.GroupId + DependsOn: AdminUserSecret + LambdaAuroraIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: allows access from lambda into aurora + GroupId: !GetAtt DBSecurityGroup.GroupId + IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupId: !Ref LambdaSecurityGroupId + BootstrapDatabaseLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref AdminUserSecret + - !Ref MaintenanceUserSecret + - !Ref ReadwriteUserSecret + - !Ref ReadonlyUserSecret + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + BootstrapDatabaseLambdaFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} - S3Key: fn/{{version}}/CreateSchema.zip + S3Key: fn/{{version}}/BootstrapDatabase.zip Description: Database Init Environment: Variables: AWS_STACK_NAME: !Ref AWS::StackName - DATABASE_USER: !Ref DBMasterUserName - DATABASE_SECRET_ARN: !Ref DBSecret - AURORA_DB_HOST: !GetAtt RDSCluster.Endpoint.Address - SECRETS_MANAGER_SECRET_ID: !Sub "${AWS::StackName}-AuroraUserSecret" - FunctionName: !Sub ${StackName}-CreateSchema - Handler: "index.handle" - MemorySize: 128 - Role: !GetAtt CreateSchemaLambdaRole.Arn - Runtime: "nodejs12.x" - Timeout: 120 #seconds + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + ADMIN_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-AdminUserSecret + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret + READWRITE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadwriteUserSecret + READONLY_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadonlyUserSecret + DATABASE_NAME: !Ref DatabaseName + FunctionName: !Sub ${StackName}-BootstrapDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt BootstrapDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 60 VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroupId @@ -122,10 +208,77 @@ Resources: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet DependsOn: RDSCluster - CreateSchemaLambdaCustomResource: - Type: "Custom::CreateSchemaLambdaInvoker" + BootstrapDatabaseLambdaLambdaInvoker: + Type: Custom::BootstrapDatabaseLambdaInvoker Properties: - ServiceToken: !GetAtt CreateSchemaLambdaFunction.Arn + ServiceToken: !GetAtt BootstrapDatabaseLambdaFunction.Arn + MigrateDatabaseLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref MaintenanceUserSecret + - Effect: Allow + Action: + - s3:ListBucket + Resource: + - arn:aws:s3:::{{awsReleaseBucket}} + - Effect: Allow + Action: + - s3:GetObject* + Resource: + - arn:aws:s3:::{{awsReleaseBucket}}/* + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + MigrateDatabaseLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/MigrateDatabase.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref AWS::StackName + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret + DATABASE_NAME: !Ref DatabaseName + MIGRATIONS_BUCKET: {{awsReleaseBucket}} + MIGRATIONS_LOCATION: migrations/{{version}} + FunctionName: !Sub ${StackName}-MigrateDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt MigrateDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 180 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + DependsOn: RDSCluster + MigrateDatabaseLambdaLambdaInvoker: + Type: Custom::MigrateDatabaseLambdaInvoker + Properties: + ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn + DependsOn: BootstrapDatabaseLambdaLambdaInvoker Outputs: StackName: Description: Aurora Stack Name @@ -133,11 +286,17 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-StackName - DBSecretArn: - Description: DBSecret Arn - Value: !Ref DBSecret + ReadwriteUserSecretId: + Description: Secret Id for the readwrite user + Value: !Sub ${AWS::StackName}-ReadwriteUserSecret + Export: + Name: !Sub ${AWS::StackName}-ReadwriteUserSecretId + + ReadonlyUserSecretId: + Description: Secret Id for the readonly user + Value: !Sub ${AWS::StackName}-ReadonlyUserSecret Export: - Name: !Sub ${AWS::StackName}-DBSecretArn + Name: !Sub ${AWS::StackName}-UserSecretId DatabaseClusterArn: Description: Aurora Cluster ARN @@ -145,26 +304,8 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-DatabaseClusterArn - DatabaseSecretArn: - Description: Aurora Secret ARN - Value: !Ref DBSecret - Export: - Name: !Sub ${AWS::StackName}-DatabaseSecretArn - - DatabaseClusterID: - Description: Aurora Cluster ID - Value: !Ref RDSCluster - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterID - - AuroraDbURL: - Description: Aurora Database URL + DatabaseEndpoint: + Description: Aurora Database Endpoint Value: !GetAtt RDSCluster.Endpoint.Address Export: - Name: !Sub ${AWS::StackName}-DatabaseURL - - DatabaseMasterUserName: - Description: Aurora Database User - Value: !Ref DBMasterUserName - Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName + Name: !Sub ${AWS::StackName}-DatabaseEndpoint diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 2308f345..50cc7f04 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -109,6 +109,7 @@ Resources: LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 + DependsOn: LambdaSecurityGroup S3Stack: Type: AWS::CloudFormation::Stack @@ -795,4 +796,4 @@ Outputs: Value: !GetAtt CustomStack.Outputs.CognitoUserPoolId Version: - Value: {{version}} \ No newline at end of file + Value: {{version}} diff --git a/packages/lambda/bin/release.js b/packages/lambda/bin/release.js index b0e22b2c..b01a96b6 100755 --- a/packages/lambda/bin/release.js +++ b/packages/lambda/bin/release.js @@ -59,6 +59,19 @@ const release = function (region) { }); }; +const releaseMigrations = function () { + const s3 = new S3(); + const migrationsDir = path.resolve(__dirname, './../migrations'); + const migrations = fs.readdirSync(migrationsDir); + const bucketName = config.get('release.AWS_RELEASE_BUCKET'); + const bucketRegion = config.get('release.AWS_RELEASE_BUCKET_REGION'); + migrations.forEach(function (migrationName) { + const objectName = 'migrations/' + packageJson.version + '/' + migrationName; + const body = fs.readFileSync(migrationsDir + '/' + migrationName); + return s3.putObject(bucketRegion, bucketName, objectName, body); + }); +}; + let promise = Promise.resolve(); if (process.argv[2] !== '--force' && process.argv[2] !== '-F') { config.get('release.AWS_LAMBDA_RELEASE_BUCKET_AVAILABLE_REGIONS').forEach(function (region) { @@ -80,4 +93,13 @@ promise.then(function () { console.log('Lambda functions released'); }).catch(function (err) { console.log(err); -}); \ No newline at end of file +}); + +promise.then(function () { + return releaseMigrations(); +}).then(function () { + console.log('Database migrations released'); +}).catch(function (err) { + console.log(err); +}); + diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 73a5d5e8..967a42bf 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -157,7 +157,8 @@ module.exports = { SendRegistrationPendingEmail: './src/custom/sendRegistrationPendingEmail/index.js', // Database Lambda Functions - CreateSchema: './src/database/createSchema/index.js', + BootstrapDatabase: './src/database/bootstrapDatabase/index.js', + MigrateDatabase: './src/database/migrateDatabase/index.js', }, output: { filename: '[name]/index.js', diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js new file mode 100644 index 00000000..25594895 --- /dev/null +++ b/packages/lambda/migrations/00_initial.js @@ -0,0 +1,75 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Settings', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + key: { + type: Sequelize.STRING + }, + value: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + isDeleted: { + type: Sequelize.BOOLEAN, + defaultValue: false, + allowNull: false + } + }).then( + queryInterface.createTable('Contents', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + isDeleted: { + type: Sequelize.BOOLEAN, + defaultValue: false, + allowNull: false + }, + parentId: { + type: Sequelize.INTEGER + }, + sortOrder: { + type: Sequelize.INTEGER + }, + type: { + type: Sequelize.STRING + }, + value: { + type: Sequelize.STRING + }, + name: { + type: Sequelize.STRING + } + }) + ); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Settings').then( + queryInterface.dropTable('Contents') + );; + } +}; diff --git a/packages/lambda/migrations/20200729184046-create-setting.js b/packages/lambda/migrations/20200729184046-create-setting.js deleted file mode 100644 index f75abd6b..00000000 --- a/packages/lambda/migrations/20200729184046-create-setting.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -module.exports = { - up: async (queryInterface, Sequelize) => { - await queryInterface.createTable('Settings', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - key: { - type: Sequelize.STRING - }, - value: { - type: Sequelize.STRING - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - }, - isDeleted: { - type: Sequelize.BOOLEAN, - defaultValue: false, - allowNull: false - } - }); - }, - down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable('Settings'); - } -}; \ No newline at end of file diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index bf4c6e60..a7e195a3 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -320,12 +320,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", @@ -752,8 +746,7 @@ "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { "version": "4.11.8", @@ -1185,20 +1178,6 @@ } } }, - "cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dev": true, - "requires": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1360,16 +1339,6 @@ } } }, - "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -1534,16 +1503,6 @@ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1724,42 +1683,6 @@ "safe-buffer": "^5.0.1" } }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -1825,56 +1748,12 @@ "is-arrayish": "^0.2.1" } }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1917,16 +1796,6 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -1992,23 +1861,6 @@ } } }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", - "dev": true - } - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2355,17 +2207,6 @@ "readable-stream": "^2.0.0" } }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -2397,25 +2238,29 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -2425,13 +2270,15 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, "requires": { @@ -2441,37 +2288,43 @@ }, "chownr": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "3.2.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "optional": true, "requires": { @@ -2480,25 +2333,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, "requires": { @@ -2507,13 +2364,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -2529,7 +2388,8 @@ }, "glob": { "version": "7.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "optional": true, "requires": { @@ -2543,13 +2403,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -2558,7 +2420,8 @@ }, "ignore-walk": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "optional": true, "requires": { @@ -2567,7 +2430,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -2577,19 +2441,22 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, "requires": { @@ -2598,13 +2465,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, "requires": { @@ -2613,13 +2482,15 @@ }, "minimist": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true, "optional": true }, "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "optional": true, "requires": { @@ -2629,7 +2500,8 @@ }, "minizlib": { "version": "1.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "optional": true, "requires": { @@ -2638,7 +2510,8 @@ }, "mkdirp": { "version": "0.5.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", "dev": true, "optional": true, "requires": { @@ -2647,13 +2520,15 @@ }, "ms": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "optional": true }, "needle": { "version": "2.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", "dev": true, "optional": true, "requires": { @@ -2664,7 +2539,8 @@ }, "node-pre-gyp": { "version": "0.14.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "dev": true, "optional": true, "requires": { @@ -2682,7 +2558,8 @@ }, "nopt": { "version": "4.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "optional": true, "requires": { @@ -2692,7 +2569,8 @@ }, "npm-bundled": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "optional": true, "requires": { @@ -2701,13 +2579,15 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "dev": true, "optional": true, "requires": { @@ -2718,7 +2598,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -2730,19 +2611,22 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, "requires": { @@ -2751,19 +2635,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -2773,19 +2660,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -2797,7 +2687,8 @@ }, "readable-stream": { "version": "2.3.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "optional": true, "requires": { @@ -2812,7 +2703,8 @@ }, "rimraf": { "version": "2.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "optional": true, "requires": { @@ -2821,43 +2713,50 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, "requires": { @@ -2868,7 +2767,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -2877,7 +2777,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, "requires": { @@ -2886,13 +2787,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.13", - "bundled": true, + "resolved": false, + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "optional": true, "requires": { @@ -2907,13 +2810,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -2922,13 +2827,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "optional": true } @@ -3278,12 +3185,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, "inquirer": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz", @@ -3793,41 +3694,6 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, - "js-beautify": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.11.0.tgz", - "integrity": "sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A==", - "dev": true, - "requires": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "~1.0.3", - "nopt": "^4.0.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -3916,15 +3782,6 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsonwebtoken": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", @@ -4175,15 +4032,6 @@ "yallist": "^3.0.2" } }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4254,22 +4102,6 @@ "p-is-promise": "^1.1.0" } }, - "memoizee": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -4643,12 +4475,6 @@ "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", "dev": true }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4728,16 +4554,6 @@ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5051,16 +4867,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -5423,12 +5229,6 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -5929,111 +5729,6 @@ } } }, - "sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "dev": true, - "requires": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.3.0", - "yargs": "^13.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -6099,12 +5794,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6784,16 +6473,6 @@ "setimmediate": "^1.0.4" } }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, "title-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", @@ -6929,12 +6608,6 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, "type-detect": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", @@ -6970,7 +6643,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", - "dev": true, "requires": { "bluebird": "^3.7.2" } @@ -7016,12 +6688,6 @@ "imurmurhash": "^0.1.4" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 8d240d5b..42bf4e59 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -28,6 +28,7 @@ "pg-hstore": "^2.3.3", "rimraf": "^2.6.1", "sequelize": "^6.3.3", + "umzug": "^2.3.0", "validate.js": "0.10.0" }, "devDependencies": { @@ -60,7 +61,6 @@ "randomstring": "^1.1.5", "raw-loader": "^0.5.1", "request": "^2.88.0", - "sequelize-cli": "^6.2.0", "sinon": "^2.3.6", "slug": "^0.9.3", "uuid-validate": "0.0.2", diff --git a/packages/lambda/src/aws/s3.js b/packages/lambda/src/aws/s3.js index b4da02cd..1a06a0b4 100644 --- a/packages/lambda/src/aws/s3.js +++ b/packages/lambda/src/aws/s3.js @@ -16,6 +16,8 @@ const AWS = require('aws-sdk'); const mime = require('mime'); +const fs = require('fs'); +const path = require('path'); /** * S3 constructor @@ -49,6 +51,37 @@ S3.prototype.getObject = function (region, bucketName, objectName) { }); }; +/** + * Download an object from AWS S3 + * + * @param {string} region + * @param {string} bucketName + * @param {string} objectName + * @param {string} destPath + * @return {Promise} + */ +S3.prototype.downloadObject = function (region, bucketName, objectName, destPath) { + const awsS3 = new AWS.S3({region: region}); + return new Promise(function (resolve, reject) { + const params = { + Bucket: bucketName, + Key: objectName + }; + awsS3.getObject(params, function (err, result) { + if (err) { + reject(err); + } + + var filepath = path.join(destPath, objectName); + fs.mkdirSync(path.dirname(filepath), {recursive: true}); + if (result['ContentType'] != 'application/x-directory') { + fs.writeFileSync(filepath, result.Body.toString()); + } + resolve(result); + }); + }); +}; + /** * Put an object on AWS S3 * @@ -198,4 +231,4 @@ S3.prototype.getSignedUrl = function (region, bucketName, filePath, contentType, }); }; -module.exports = S3; \ No newline at end of file +module.exports = S3; diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js new file mode 100644 index 00000000..98e9eda9 --- /dev/null +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -0,0 +1,83 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const logger = require('./../../helpers/log'); +const response = require('cfn-response'); +const Request = require('./../../aws/request'); +const SecretsManager = require('./../../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); + +exports.handle = function (event, context, callback) { + logger.log('bootstrapDatabase event: %j', event); + + const request = new Request(event, context); + const secretsManager = new SecretsManager(); + + if (event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS); + return; + } + + request.validate().then(function () { + return Promise.all([ + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.ADMIN_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READONLY_DATABASE_SECRET_ID) + ]); + }).then(function (secrets) { + const dbHost = process.env.DATABASE_HOST; + const dbName = process.env.DATABASE_NAME; + const adminSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.ADMIN_DATABASE_SECRET_ID).SecretString); + const maintenanceSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.MAINTENANCE_DATABASE_SECRET_ID).SecretString); + const readwriteSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READWRITE_DATABASE_SECRET_ID).SecretString); + const readonlySecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READONLY_DATABASE_SECRET_ID).SecretString); + + const sequelize = new Sequelize({ + host: dbHost, + username: adminSecret.username, + password: adminSecret.password, + dialect: 'mysql', + dialectModule: mysql2, + port: 3306, + logging: false, // don't log the sql so we don't log the passwords + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS', + multipleStatements: true + } + }); + + // TODO: Add REQUIRE SSL to the grants + return sequelize.query( + 'CREATE DATABASE IF NOT EXISTS `' + dbName + '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; ' + + 'CREATE USER IF NOT EXISTS "' + maintenanceSecret.username + '"@"%" IDENTIFIED BY "' + maintenanceSecret.password + '"; ' + + 'GRANT ALL PRIVILEGES ON `' + dbName+ '`.* TO "' + maintenanceSecret.username + '"@"%"; ' + + 'CREATE USER IF NOT EXISTS "' + readwriteSecret.username + '"@"%" IDENTIFIED BY "' + readwriteSecret.password + '"; ' + + 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%"; ' + + 'CREATE USER IF NOT EXISTS "' + readonlySecret.username + '"@"%" IDENTIFIED BY "' + readonlySecret.password + '"; ' + + 'GRANT SELECT ON `' + dbName+ '`.* TO "' + readonlySecret.username + '"@"%";' + ); + }).then(function () { + response.send(event, context, response.SUCCESS); + callback(); + }).catch(function (err) { + logger.log(err); + response.send(event, context, response.FAILED); + callback(err); + }); +}; diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js deleted file mode 100644 index 0ca0eba4..00000000 --- a/packages/lambda/src/database/createSchema/index.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 Firespring, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const response = require('cfn-response'); -const Request = require('./../../aws/request'); -const SecretsManager = require('./../../aws/secretsManager'); -const Sequelize = require('sequelize'); -const mysql2 = require('mysql2'); - -exports.handle = function (event, context, callback) { - console.log(JSON.stringify(event)); - const secretsManager = new SecretsManager(); - const request = new Request(event, context); - - if (event.RequestType === 'Update' || event.RequestType === 'Delete') { - response.send(event, context, response.SUCCESS, {}); - return; - } - - request.validate().then(function () { - return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID); - }).then(function (res) { - const sequelize = new Sequelize('', process.env.DATABASE_USER, JSON.parse(res.SecretString).password, { - host: process.env.AURORA_DB_HOST, - dialect: 'mysql', - dialectModule: mysql2, - port: 3306, - dialectOptions: { - ssl: { - rejectUnauthorized: false - } - } - }); - - return sequelize.query("CREATE DATABASE IF NOT EXIST 'givesource' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;"); - }).then(function (res) { - console.log(res); /*DM: Debug */ - response.send(event, context, response.SUCCESS, {}); - callback(); - }).catch(function (err) { - console.log(err); - response.send(event, context, response.FAILED, {}); - callback(err); - }); -}; diff --git a/packages/lambda/src/database/migrateDatabase/index.js b/packages/lambda/src/database/migrateDatabase/index.js new file mode 100644 index 00000000..150e8643 --- /dev/null +++ b/packages/lambda/src/database/migrateDatabase/index.js @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const fs = require('fs'); +const path = require('path'); +const logger = require('./../../helpers/log'); +const response = require('cfn-response'); +const Request = require('./../../aws/request'); +const S3 = require('./../../aws/s3'); +const SecretsManager = require('./../../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); +const Umzug = require('umzug'); + +exports.handle = function (event, context, callback) { + logger.log('migrateDatabase event: %j', event); + + const secretsManager = new SecretsManager(); + const request = new Request(event, context); + const s3 = new S3(); + const localPath = '/tmp'; + + if (event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS); + return; + } + + request.validate().then(function () { + fs.rmdirSync(path.join(localPath, process.env.MIGRATIONS_LOCATION), {recursive: true}); + return s3.listObjects(process.env.AWS_REGION, process.env.MIGRATIONS_BUCKET, process.env.MIGRATIONS_LOCATION).then(function (objects) { + return Promise.all(objects.map(function (obj) { + return s3.downloadObject(process.env.AWS_REGION, process.env.MIGRATIONS_BUCKET, obj.Key, localPath); + })); + }); + }).then(function () { + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID); + }).then(function (secret) { + const dbHost = process.env.DATABASE_HOST; + const dbName = process.env.DATABASE_NAME; + const maintenanceSecret = JSON.parse(secret.SecretString); + const sequelize = new Sequelize({ + host: dbHost, + username: maintenanceSecret.username, + password: maintenanceSecret.password, + database: dbName, + dialect: 'mysql', + dialectModule: mysql2, + port: 3306, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } + }); + + const umzug = new Umzug({ + migrations: { + path: path.join(localPath, process.env.MIGRATIONS_LOCATION), + params: [ + sequelize.getQueryInterface(), + Sequelize + ], + customResolver: function (filePath) { + return __non_webpack_require__(filePath); + }, + }, + storage: 'sequelize', + storageOptions: { + sequelize: sequelize + } + }) + + return umzug.up(); + }).then(function (migrations) { + logger.log("Ran migrations:" + migrations.map(it => { return it['file'] })); + response.send(event, context, response.SUCCESS, {}); + callback(); + }).catch(function (err) { + logger.log(err); + response.send(event, context, response.FAILED, {}); + callback(err); + }); +}; From 1d9c9b5f682e35f59eec05e52def9396f10b1352 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 6 Aug 2020 15:57:43 -0500 Subject: [PATCH 029/140] WIP --- packages/lambda/migrations/00_initial.js | 377 ++++++++++++++++++++--- 1 file changed, 342 insertions(+), 35 deletions(-) diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 25594895..af0e5512 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -2,74 +2,381 @@ module.exports = { up: async (queryInterface, Sequelize) => { - await queryInterface.createTable('Settings', { + queryInterface.createTable('Contents', { id: { + type: Sequelize.INTEGER(11), allowNull: false, autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER + primaryKey: true }, - key: { - type: Sequelize.STRING + parentId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, }, - value: { - type: Sequelize.STRING + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, }, - createdAt: { + type: { + type: Sequelize.STRING(50), allowNull: false, - type: Sequelize.DATE }, - updatedAt: { + value: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), allowNull: false, - type: Sequelize.DATE }, isDeleted: { type: Sequelize.BOOLEAN, + allowNull: false, defaultValue: false, - allowNull: false + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' } }).then( - queryInterface.createTable('Contents', { + queryInterface.createTable('Donations', { id: { + type: Sequelize.INTEGER(11), allowNull: false, autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER + primaryKey: true + } + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + //count` INT(11) NOT NULL DEFAULT 0, ' + + //fees` INT(11) NOT NULL DEFAULT 0, ' + + //isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + + //isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + + //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + //paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + //paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + + //subtotal` INT(11) NOT NULL DEFAULT 0, ' + + //subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + + //total` INT(11) NOT NULL DEFAULT 0, ' + + //type` TINYINT(1) NOT NULL DEFAULT 0, ' + + //donorId` INT(11) NOT NULL DEFAULT 0, ' + + //note` VARCHAR(255) DEFAULT NULL, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + + //KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + + //KEY `ix_donations_donor_id` (`donorId`) ' + + }) + ).then( + queryInterface.createTable('Donors', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + } + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + + //address1` VARCHAR(50) NOT NULL, ' + + //address2` VARCHAR(50) NOT NULL, ' + + //city` VARCHAR(50) NOT NULL, ' + + //email` VARCHAR(50) NOT NULL, ' + + //firstName` VARCHAR(50) NOT NULL, ' + + //lastName` VARCHAR(50) NOT NULL, ' + + //phone` VARCHAR(50) NOT NULL, ' + + //state` VARCHAR(50) NOT NULL, ' + + //zip` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_donors_email` (`email`) ' + + // + }) + ).then( + queryInterface.createTable('Files', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true }, - createdAt: { + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //path` VARCHAR(50) NOT NULL, ' + + //filename` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`) ' + + // + }) + ).then( + queryInterface.createTable('Messages', { + id: { + type: Sequelize.INTEGER(11), allowNull: false, - type: Sequelize.DATE + autoIncrement: true, + primaryKey: true }, - updatedAt: { + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //email` VARCHAR(50) NOT NULL, ' + + //name` VARCHAR(50) NOT NULL, ' + + //message` VARCHAR(50) NOT NULL, ' + + //phone` VARCHAR(50) NOT NULL, ' + + //type` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`) ' + + // + }) + ).then( + queryInterface.createTable('Metrics', { + id: { + type: Sequelize.INTEGER(11), allowNull: false, - type: Sequelize.DATE + autoIncrement: true, + primaryKey: true }, - isDeleted: { - type: Sequelize.BOOLEAN, - defaultValue: false, - allowNull: false + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //key` VARCHAR(50) NOT NULL, ' + + //value` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`) ' + + // + }) + ).then( + queryInterface.createTable('NonprofitDonationTiers', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true }, - parentId: { - type: Sequelize.INTEGER + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //amount` INT(11) NOT NULL DEFAULT 0, ' + + //description` VARCHAR(255) NOT NULL, ' + + //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + + // + }) + ).then( + queryInterface.createTable('Nonprofits', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true }, - sortOrder: { - type: Sequelize.INTEGER + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //address1` VARCHAR(50) NOT NULL, ' + + //address2` VARCHAR(50) NOT NULL, ' + + //category1` INT(11) NOT NULL DEFAULT 0, ' + + //category2` INT(11) NOT NULL DEFAULT 0, ' + + //category3` INT(11) NOT NULL DEFAULT 0, ' + + //city` VARCHAR(50) NOT NULL, ' + + //email` VARCHAR(50) NOT NULL, ' + + //firstName` VARCHAR(50) NOT NULL, ' + + //lastName` VARCHAR(50) NOT NULL, ' + + //phone` VARCHAR(50) NOT NULL, ' + + //state` VARCHAR(50) NOT NULL, ' + + //zip` VARCHAR(50) NOT NULL, ' + + //legalName` VARCHAR(50) NOT NULL, ' + + //legalNameSearch` VARCHAR(50) NOT NULL, ' + + //logoFileId` INT(11) NOT NULL DEFAULT 0, ' + + //longDescription` VARCHAR(255) NOT NULL, ' + + //receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + + //shortDescription` VARCHAR(50) NOT NULL, ' + + //slug` VARCHAR(50) NOT NULL, ' + + //socialSharingDescription` VARCHAR(50) NOT NULL, ' + + //socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + + //status` VARCHAR(50) NOT NULL, ' + + //taxId` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + + //KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + + //KEY `ix_nonprofits_slug` (`slug`) ' + + // + }) + ).then( + queryInterface.createTable('NonprofitSlides', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true }, - type: { - type: Sequelize.STRING + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + //caption` VARCHAR(50) NOT NULL, ' + + //embedUrl` VARCHAR(50) NOT NULL, ' + + //externalId` VARCHAR(50) NOT NULL, ' + + //thumbnail` VARCHAR(50) NOT NULL, ' + + //type` VARCHAR(50) NOT NULL, ' + + //url` VARCHAR(50) NOT NULL, ' + + //fileId` INT(11) NOT NULL DEFAULT 0, ' + + //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + + // + }) + ).then( + queryInterface.createTable('PaymentTransactions', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //billingZip` VARCHAR(50) NOT NULL, ' + + //creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + + //creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + + //creditCardLast4` VARCHAR(50) NOT NULL, ' + + //creditCardName` VARCHAR(50) NOT NULL, ' + + //creditCardType` VARCHAR(50) NOT NULL, ' + + //isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + + //transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + + //transactionId` VARCHAR(50) NOT NULL, ' + + //transactionStatus` VARCHAR(50) NOT NULL, ' + + //PRIMARY KEY (`id`) ' + + // + }) + ).then( + queryInterface.createTable('Reports', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //status` VARCHAR(50) NOT NULL, ' + + //type` VARCHAR(50) NOT NULL, ' + + //fileId` INT(11) NOT NULL DEFAULT 0, ' + + //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + + //PRIMARY KEY (`id`) ' + + // + }) + ).then( + queryInterface.createTable('Settings', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + key: { + type: Sequelize.STRING(50), + allowNull: false }, value: { - type: Sequelize.STRING + type: Sequelize.STRING(50), + allowNull: false + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false }, - name: { - type: Sequelize.STRING + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false + defaultValue: '0000-00-00 00:00:00' } }) + ).then( + queryInterface.createTable('Sponsors', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //logoUrl` VARCHAR(50) NOT NULL, ' + + //name` VARCHAR(50) NOT NULL, ' + + //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + //url` VARCHAR(50) NOT NULL, ' + + //fileId` INT(11) NOT NULL DEFAULT 0, ' + + //sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + + // + }) + ).then( + queryInterface.createTable('SponsorTiers', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + //id` INT(11) NOT NULL, ' + + //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + + //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + + //name` VARCHAR(50) NOT NULL, ' + + //size` VARCHAR(50) NOT NULL, ' + + //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + + //PRIMARY KEY (`id`), ' + + //KEY `ix_sponsor_tiers_name` (`name`) ' + + // + }) ); }, down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable('Settings').then( - queryInterface.dropTable('Contents') - );; + await queryInterface.dropTable('Contents').then( + queryInterface.dropTable('Donations') + ).then( + queryInterface.dropTable('Donors') + ).then( + queryInterface.dropTable('Files') + ).then( + queryInterface.dropTable('Messages') + ).then( + queryInterface.dropTable('Metrics') + ).then( + queryInterface.dropTable('NonprofitDonationTiers') + ).then( + queryInterface.dropTable('Nonprofits') + ).then( + queryInterface.dropTable('NonprofitSlides') + ).then( + queryInterface.dropTable('PaymentTransactions') + ).then( + queryInterface.dropTable('Reports') + ).then( + queryInterface.dropTable('Settings') + ).then( + queryInterface.dropTable('Sponsors') + ).then( + queryInterface.dropTable('SponsorTiers') + ); } }; From d490ae7da1052ae5d7667ea9aeeb385bc9c454e4 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 7 Aug 2020 07:33:27 -0500 Subject: [PATCH 030/140] WIP --- packages/lambda/migrations/00_initial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index af0e5512..848206bd 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -305,7 +305,7 @@ module.exports = { }, updatedAt: { type: Sequelize.DATE, - allowNull: false + allowNull: false, defaultValue: '0000-00-00 00:00:00' } }) From d690c98ec88f6ce475e776583e4cb2497b3919c4 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 7 Aug 2020 07:43:54 -0500 Subject: [PATCH 031/140] WIP --- packages/lambda/migrations/00_initial.js | 170 ++++++++++------------- 1 file changed, 74 insertions(+), 96 deletions(-) diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 848206bd..69db9b81 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -2,51 +2,52 @@ module.exports = { up: async (queryInterface, Sequelize) => { - queryInterface.createTable('Contents', { - id: { - type: Sequelize.INTEGER(11), - allowNull: false, - autoIncrement: true, - primaryKey: true - }, - parentId: { - type: Sequelize.INTEGER(11), - allowNull: false, - defaultValue: 0, - }, - sortOrder: { - type: Sequelize.INTEGER(11), - allowNull: false, - defaultValue: 0, - }, - type: { - type: Sequelize.STRING(50), - allowNull: false, - }, - value: { - type: Sequelize.STRING(50), - allowNull: false, - }, - name: { - type: Sequelize.STRING(50), - allowNull: false, - }, - isDeleted: { - type: Sequelize.BOOLEAN, - allowNull: false, - defaultValue: false, - }, - createdAt: { - type: Sequelize.DATE, - allowNull: false, - defaultValue: '0000-00-00 00:00:00' - }, - updatedAt: { - type: Sequelize.DATE, - allowNull: false, - defaultValue: '0000-00-00 00:00:00' - } - }).then( + await Promise.all([ + queryInterface.createTable('Contents', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + parentId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + value: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), queryInterface.createTable('Donations', { id: { type: Sequelize.INTEGER(11), @@ -76,8 +77,7 @@ module.exports = { //KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + //KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + //KEY `ix_donations_donor_id` (`donorId`) ' + - }) - ).then( + }), queryInterface.createTable('Donors', { id: { type: Sequelize.INTEGER(11), @@ -101,8 +101,7 @@ module.exports = { //PRIMARY KEY (`id`), ' + //KEY `ix_donors_email` (`email`) ' + // - }) - ).then( + }), queryInterface.createTable('Files', { id: { type: Sequelize.INTEGER(11), @@ -117,8 +116,7 @@ module.exports = { //filename` VARCHAR(50) NOT NULL, ' + //PRIMARY KEY (`id`) ' + // - }) - ).then( + }), queryInterface.createTable('Messages', { id: { type: Sequelize.INTEGER(11), @@ -136,8 +134,7 @@ module.exports = { //type` VARCHAR(50) NOT NULL, ' + //PRIMARY KEY (`id`) ' + // - }) - ).then( + }), queryInterface.createTable('Metrics', { id: { type: Sequelize.INTEGER(11), @@ -152,8 +149,7 @@ module.exports = { //value` VARCHAR(50) NOT NULL, ' + //PRIMARY KEY (`id`) ' + // - }) - ).then( + }), queryInterface.createTable('NonprofitDonationTiers', { id: { type: Sequelize.INTEGER(11), @@ -170,8 +166,7 @@ module.exports = { //PRIMARY KEY (`id`), ' + //KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + // - }) - ).then( + }), queryInterface.createTable('Nonprofits', { id: { type: Sequelize.INTEGER(11), @@ -210,8 +205,7 @@ module.exports = { //KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + //KEY `ix_nonprofits_slug` (`slug`) ' + // - }) - ).then( + }), queryInterface.createTable('NonprofitSlides', { id: { type: Sequelize.INTEGER(11), @@ -234,8 +228,7 @@ module.exports = { //PRIMARY KEY (`id`), ' + //KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + // - }) - ).then( + }), queryInterface.createTable('PaymentTransactions', { id: { type: Sequelize.INTEGER(11), @@ -258,8 +251,7 @@ module.exports = { //transactionStatus` VARCHAR(50) NOT NULL, ' + //PRIMARY KEY (`id`) ' + // - }) - ).then( + }), queryInterface.createTable('Reports', { id: { type: Sequelize.INTEGER(11), @@ -276,8 +268,7 @@ module.exports = { //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + //PRIMARY KEY (`id`) ' + // - }) - ).then( + }), queryInterface.createTable('Settings', { id: { type: Sequelize.INTEGER(11), @@ -308,8 +299,7 @@ module.exports = { allowNull: false, defaultValue: '0000-00-00 00:00:00' } - }) - ).then( + }), queryInterface.createTable('Sponsors', { id: { type: Sequelize.INTEGER(11), @@ -329,8 +319,7 @@ module.exports = { //PRIMARY KEY (`id`), ' + //KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + // - }) - ).then( + }), queryInterface.createTable('SponsorTiers', { id: { type: Sequelize.INTEGER(11), @@ -348,35 +337,24 @@ module.exports = { //KEY `ix_sponsor_tiers_name` (`name`) ' + // }) - ); + ]); }, down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable('Contents').then( - queryInterface.dropTable('Donations') - ).then( - queryInterface.dropTable('Donors') - ).then( - queryInterface.dropTable('Files') - ).then( - queryInterface.dropTable('Messages') - ).then( - queryInterface.dropTable('Metrics') - ).then( - queryInterface.dropTable('NonprofitDonationTiers') - ).then( - queryInterface.dropTable('Nonprofits') - ).then( - queryInterface.dropTable('NonprofitSlides') - ).then( - queryInterface.dropTable('PaymentTransactions') - ).then( - queryInterface.dropTable('Reports') - ).then( - queryInterface.dropTable('Settings') - ).then( - queryInterface.dropTable('Sponsors') - ).then( + await Promise.all([ + queryInterface.dropTable('Contents'), + queryInterface.dropTable('Donations'), + queryInterface.dropTable('Donors'), + queryInterface.dropTable('Files'), + queryInterface.dropTable('Messages'), + queryInterface.dropTable('Metrics'), + queryInterface.dropTable('NonprofitDonationTiers'), + queryInterface.dropTable('Nonprofits'), + queryInterface.dropTable('NonprofitSlides'), + queryInterface.dropTable('PaymentTransactions'), + queryInterface.dropTable('Reports'), + queryInterface.dropTable('Settings'), + queryInterface.dropTable('Sponsors'), queryInterface.dropTable('SponsorTiers') - ); + ]); } }; From daa978152f5f477beb0e6980c0188b8398f6483e Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 7 Aug 2020 10:47:21 -0500 Subject: [PATCH 032/140] WIP --- packages/lambda/migrations/00_initial.js | 760 ++++++++++++++++++----- 1 file changed, 598 insertions(+), 162 deletions(-) diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 69db9b81..3bc1d6cb 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -54,29 +54,96 @@ module.exports = { allowNull: false, autoIncrement: true, primaryKey: true + }, + amountForNonprofit: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + count: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + fees: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isAnonymous: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + isFeeCovered: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + isOfflineDonation: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + paymentTransactionIsTestMode: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + paymentTransactionId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + subtotal: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + subtotalChargedToCard: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + total: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + type: { + type: Sequelize.TINYINT(1), + allowNull: false, + defaultValue: 0 + }, + donorId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + name: { + type: Sequelize.STRING(255), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' } - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - //count` INT(11) NOT NULL DEFAULT 0, ' + - //fees` INT(11) NOT NULL DEFAULT 0, ' + - //isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + - //isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + - //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - //paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - //paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + - //subtotal` INT(11) NOT NULL DEFAULT 0, ' + - //subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + - //total` INT(11) NOT NULL DEFAULT 0, ' + - //type` TINYINT(1) NOT NULL DEFAULT 0, ' + - //donorId` INT(11) NOT NULL DEFAULT 0, ' + - //note` VARCHAR(255) DEFAULT NULL, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + - //KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + - //KEY `ix_donations_donor_id` (`donorId`) ' + }), queryInterface.createTable('Donors', { id: { @@ -84,23 +151,63 @@ module.exports = { allowNull: false, autoIncrement: true, primaryKey: true + }, + amountForNonprofit: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + address1: { + type: Sequelize.STRING(50), + allowNull: false, + }, + address2: { + type: Sequelize.STRING(50), + allowNull: false, + }, + city: { + type: Sequelize.STRING(50), + allowNull: false, + }, + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + firstName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + lastName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + state: { + type: Sequelize.STRING(50), + allowNull: false, + }, + zip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' } - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - //address1` VARCHAR(50) NOT NULL, ' + - //address2` VARCHAR(50) NOT NULL, ' + - //city` VARCHAR(50) NOT NULL, ' + - //email` VARCHAR(50) NOT NULL, ' + - //firstName` VARCHAR(50) NOT NULL, ' + - //lastName` VARCHAR(50) NOT NULL, ' + - //phone` VARCHAR(50) NOT NULL, ' + - //state` VARCHAR(50) NOT NULL, ' + - //zip` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_donors_email` (`email`) ' + - // }), queryInterface.createTable('Files', { id: { @@ -109,13 +216,29 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //path` VARCHAR(50) NOT NULL, ' + - //filename` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`) ' + - // + path: { + type: Sequelize.STRING(50), + allowNull: false, + }, + filename: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('Messages', { id: { @@ -124,16 +247,41 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //email` VARCHAR(50) NOT NULL, ' + - //name` VARCHAR(50) NOT NULL, ' + - //message` VARCHAR(50) NOT NULL, ' + - //phone` VARCHAR(50) NOT NULL, ' + - //type` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`) ' + - // + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + message: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('Metrics', { id: { @@ -142,13 +290,29 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //key` VARCHAR(50) NOT NULL, ' + - //value` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`) ' + - // + key: { + type: Sequelize.STRING(50), + allowNull: false, + }, + value: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('NonprofitDonationTiers', { id: { @@ -157,15 +321,35 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //amount` INT(11) NOT NULL DEFAULT 0, ' + - //description` VARCHAR(255) NOT NULL, ' + - //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + - // + amount: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + value: { + type: Sequelize.STRING(255), + allowNull: false, + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('Nonprofits', { id: { @@ -174,37 +358,119 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //address1` VARCHAR(50) NOT NULL, ' + - //address2` VARCHAR(50) NOT NULL, ' + - //category1` INT(11) NOT NULL DEFAULT 0, ' + - //category2` INT(11) NOT NULL DEFAULT 0, ' + - //category3` INT(11) NOT NULL DEFAULT 0, ' + - //city` VARCHAR(50) NOT NULL, ' + - //email` VARCHAR(50) NOT NULL, ' + - //firstName` VARCHAR(50) NOT NULL, ' + - //lastName` VARCHAR(50) NOT NULL, ' + - //phone` VARCHAR(50) NOT NULL, ' + - //state` VARCHAR(50) NOT NULL, ' + - //zip` VARCHAR(50) NOT NULL, ' + - //legalName` VARCHAR(50) NOT NULL, ' + - //legalNameSearch` VARCHAR(50) NOT NULL, ' + - //logoFileId` INT(11) NOT NULL DEFAULT 0, ' + - //longDescription` VARCHAR(255) NOT NULL, ' + - //receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + - //shortDescription` VARCHAR(50) NOT NULL, ' + - //slug` VARCHAR(50) NOT NULL, ' + - //socialSharingDescription` VARCHAR(50) NOT NULL, ' + - //socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + - //status` VARCHAR(50) NOT NULL, ' + - //taxId` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + - //KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + - //KEY `ix_nonprofits_slug` (`slug`) ' + - // + address1: { + type: Sequelize.STRING(50), + allowNull: false, + }, + address2: { + type: Sequelize.STRING(50), + allowNull: false, + }, + category1: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + category2: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + category3: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + city: { + type: Sequelize.STRING(50), + allowNull: false, + }, + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + firstName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + lastName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + state: { + type: Sequelize.STRING(50), + allowNull: false, + }, + zip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + legalName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + legalNameSearch: { + type: Sequelize.STRING(50), + allowNull: false, + }, + logoFileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + longDescription: { + type: Sequelize.STRING(255), + allowNull: false, + }, + category3: { + type: Sequelize.TINYINT(1), + allowNull: false, + defaultValue: 0 + }, + shortDescription: { + type: Sequelize.STRING(50), + allowNull: false, + }, + slug: { + type: Sequelize.STRING(50), + allowNull: false, + }, + socialSharingDescription: { + type: Sequelize.STRING(50), + allowNull: false, + }, + socialSharingFileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + status: { + type: Sequelize.STRING(50), + allowNull: false, + }, + taxId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('NonprofitSlides', { id: { @@ -213,21 +479,60 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - //caption` VARCHAR(50) NOT NULL, ' + - //embedUrl` VARCHAR(50) NOT NULL, ' + - //externalId` VARCHAR(50) NOT NULL, ' + - //thumbnail` VARCHAR(50) NOT NULL, ' + - //type` VARCHAR(50) NOT NULL, ' + - //url` VARCHAR(50) NOT NULL, ' + - //fileId` INT(11) NOT NULL DEFAULT 0, ' + - //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + - // + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + caption: { + type: Sequelize.STRING(50), + allowNull: false, + }, + embedUrl: { + type: Sequelize.STRING(50), + allowNull: false, + }, + externalId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + thumbnail: { + type: Sequelize.STRING(50), + allowNull: false, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + url: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('PaymentTransactions', { id: { @@ -236,21 +541,65 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //billingZip` VARCHAR(50) NOT NULL, ' + - //creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + - //creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + - //creditCardLast4` VARCHAR(50) NOT NULL, ' + - //creditCardName` VARCHAR(50) NOT NULL, ' + - //creditCardType` VARCHAR(50) NOT NULL, ' + - //isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - //transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + - //transactionId` VARCHAR(50) NOT NULL, ' + - //transactionStatus` VARCHAR(50) NOT NULL, ' + - //PRIMARY KEY (`id`) ' + - // + billingZip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardExpirationMonth: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + creditCardExpirationYear: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + creditCardLast4: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardType: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isTestMode: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + transactionAmount: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + transactionId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + transactionStatus: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('Reports', { id: { @@ -259,15 +608,39 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //status` VARCHAR(50) NOT NULL, ' + - //type` VARCHAR(50) NOT NULL, ' + - //fileId` INT(11) NOT NULL DEFAULT 0, ' + - //nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - //PRIMARY KEY (`id`) ' + - // + status: { + type: Sequelize.STRING(50), + allowNull: false, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('Settings', { id: { @@ -307,18 +680,48 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //logoUrl` VARCHAR(50) NOT NULL, ' + - //name` VARCHAR(50) NOT NULL, ' + - //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - //url` VARCHAR(50) NOT NULL, ' + - //fileId` INT(11) NOT NULL DEFAULT 0, ' + - //sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + - // + logoUrl: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + url: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + sponsorTierId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }), queryInterface.createTable('SponsorTiers', { id: { @@ -327,17 +730,50 @@ module.exports = { autoIncrement: true, primaryKey: true }, - //id` INT(11) NOT NULL, ' + - //createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - //isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - //name` VARCHAR(50) NOT NULL, ' + - //size` VARCHAR(50) NOT NULL, ' + - //sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - //PRIMARY KEY (`id`), ' + - //KEY `ix_sponsor_tiers_name` (`name`) ' + - // + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + size: { + type: Sequelize.STRING(50), + allowNull: false, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }) ]); + + await Promise.all([ + queryInterface.addIndex('Donations', ['nonprofitId']), + queryInterface.addIndex('Donations', ['paymentTransactionId']), + queryInterface.addIndex('Donations', ['donorId']), + queryInterface.addIndex('Donors', ['email']), + queryInterface.addIndex('NonprofitDonationTiers', ['nonprofitId']), + queryInterface.addIndex('Nonprofits', ['isDeleted']), + queryInterface.addIndex('Nonprofits', ['status', 'legalNameSearch', 'isDeleted']), + queryInterface.addIndex('Nonprofits', ['slug']), + queryInterface.addIndex('NonprofitSlides', ['nonprofitId']), + queryInterface.addIndex('Sponsors', ['sponsorTierId']), + queryInterface.addIndex('SponsorTiers', ['name']), + ]); }, down: async (queryInterface, Sequelize) => { await Promise.all([ From 244bcdea7b6529f7b3a5f6d7b2cd9c78c0952004 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 7 Aug 2020 15:45:02 -0500 Subject: [PATCH 033/140] WIP --- packages/lambda/models/index.js | 37 ----------- packages/lambda/models/setting.js | 24 -------- .../lambda/src/api/deleteSettings/index.js | 4 +- packages/lambda/src/api/getSetting/index.js | 2 +- packages/lambda/src/api/getSettings/index.js | 8 ++- packages/lambda/src/api/patchSetting/index.js | 4 +- .../lambda/src/api/patchSettings/index.js | 4 +- packages/lambda/src/api/postSetting/index.js | 4 +- .../lambda/src/custom/saveSettings/index.js | 4 +- packages/lambda/src/models/setting.js | 61 ------------------- packages/lambda/src/repositories/settings.js | 4 +- packages/lambda/src/sql-models/index.js | 38 ++++++++++++ packages/lambda/src/sql-models/setting.js | 20 ++++++ 13 files changed, 77 insertions(+), 137 deletions(-) delete mode 100644 packages/lambda/models/index.js delete mode 100644 packages/lambda/models/setting.js delete mode 100644 packages/lambda/src/models/setting.js create mode 100644 packages/lambda/src/sql-models/index.js create mode 100644 packages/lambda/src/sql-models/setting.js diff --git a/packages/lambda/models/index.js b/packages/lambda/models/index.js deleted file mode 100644 index 33f09e77..00000000 --- a/packages/lambda/models/index.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const Sequelize = require('sequelize'); -const basename = path.basename(__filename); -const env = process.env.NODE_ENV || 'development'; -const config = require(__dirname + '/../config/config.json')[env]; -const db = {}; - -let sequelize; -if (config.use_env_variable) { - sequelize = new Sequelize(process.env[config.use_env_variable], config); -} else { - sequelize = new Sequelize(config.database, config.username, config.password, config); -} - -fs - .readdirSync(__dirname) - .filter(file => { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); - }) - .forEach(file => { - const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); - db[model.name] = model; - }); - -Object.keys(db).forEach(modelName => { - if (db[modelName].associate) { - db[modelName].associate(db); - } -}); - -db.sequelize = sequelize; -db.Sequelize = Sequelize; - -module.exports = db; diff --git a/packages/lambda/models/setting.js b/packages/lambda/models/setting.js deleted file mode 100644 index 5452ebf8..00000000 --- a/packages/lambda/models/setting.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -const { - Model -} = require('sequelize'); -module.exports = (sequelize, DataTypes) => { - class Setting extends Model { - /** - * Helper method for defining associations. - * This method is not a part of Sequelize lifecycle. - * The `models/index` file will call this method automatically. - */ - static associate(models) { - // define association here - } - }; - Setting.init({ - key: DataTypes.STRING, - value: DataTypes.STRING - }, { - sequelize, - modelName: 'Setting', - }); - return Setting; -}; \ No newline at end of file diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index 8c0d8f66..f2e79e73 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); +const Setting = require('./../../sql-models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); @@ -50,4 +50,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/getSetting/index.js b/packages/lambda/src/api/getSetting/index.js index 64b21309..c35be3fe 100644 --- a/packages/lambda/src/api/getSetting/index.js +++ b/packages/lambda/src/api/getSetting/index.js @@ -29,4 +29,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/getSettings/index.js b/packages/lambda/src/api/getSettings/index.js index 6edb62af..6be7d4cb 100644 --- a/packages/lambda/src/api/getSettings/index.js +++ b/packages/lambda/src/api/getSettings/index.js @@ -24,17 +24,21 @@ exports.handle = function (event, context, callback) { const keys = request.queryParam('keys', '').split(','); request.validate().then(function () { + console.log("KEYS ARE "); + console.log(keys); if (keys.length) { return repository.batchGet(keys); } else { return repository.getAll(); } }).then(function (settings) { + console.log("SETTINGS ARE "); + console.log(settings); const results = settings.map(function (setting) { - return setting.all(); + return setting.findAll(); }); callback(null, results); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/patchSetting/index.js b/packages/lambda/src/api/patchSetting/index.js index df122919..e41ad722 100644 --- a/packages/lambda/src/api/patchSetting/index.js +++ b/packages/lambda/src/api/patchSetting/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); +const Setting = require('./../../sql-models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); @@ -46,4 +46,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index c7280138..78a6adbd 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -18,7 +18,7 @@ const _ = require('lodash'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); +const Setting = require('./../../sql-models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); @@ -64,4 +64,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index 25b68363..9e5cb1f3 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -18,7 +18,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const ResourceAlreadyExistsException = require('./../../exceptions/resourceAlreadyExists'); -const Setting = require('./../../models/setting'); +const Setting = require('./../../sql-models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); @@ -51,4 +51,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index d00c6d78..1ee4f78d 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -17,7 +17,7 @@ const _ = require('lodash'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const Setting = require('./../../models/setting'); +const Setting = require('./../../sql-models/setting'); const SettingsRepository = require('./../../repositories/settings'); const S3 = require('./../../aws/s3'); @@ -94,4 +94,4 @@ const getSettingValue = function (key, value) { }); return promise; -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/models/setting.js b/packages/lambda/src/models/setting.js deleted file mode 100644 index 0486df1e..00000000 --- a/packages/lambda/src/models/setting.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 Firespring, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const Model = require('./model'); - -/** - * Setting constructor - * - * @param {{}} [data] - * @constructor - */ -function Setting(data) { - Model.call(this, data); -} - -/** - * Extend the base Model - * - * @type {Model} - */ -Setting.prototype = new Model(); - -/** - * The allowed attributes for this model - * - * @type {[*]} - */ -Setting.prototype.attributes = [ - 'key', - 'value' -]; - -/** - * Validation constraints for this model - * - * @type {{}} - */ -Setting.prototype.constraints = { - key: { - presence: true, - type: 'string', - }, - value: { - presence: false, - }, -}; - -module.exports = Setting; \ No newline at end of file diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 95e3fec3..6b012a00 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -17,7 +17,7 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Setting = require('./../models/setting'); +const Setting = require('./../sql-models/setting'); /** * SettingsRepository constructor @@ -180,4 +180,4 @@ SettingsRepository.prototype.save = function (model) { }); }; -module.exports = SettingsRepository; \ No newline at end of file +module.exports = SettingsRepository; diff --git a/packages/lambda/src/sql-models/index.js b/packages/lambda/src/sql-models/index.js new file mode 100644 index 00000000..b64ed821 --- /dev/null +++ b/packages/lambda/src/sql-models/index.js @@ -0,0 +1,38 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const SecretsManager = require('./../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const db = {}; +console.log("IN INDEX.js"); + +const secretsManager = new SecretsManager(); +//return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID); +//console.log(secret); +//const readonlySecret = JSON.parse(secret.SecretString); +const sequelize = new Sequelize({ + //host: readonlySecret.host, + //username: readonlySecret.username, + //password: readonlySecret.password, + //port: readonlySecret.port, + host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/packages/lambda/src/sql-models/setting.js b/packages/lambda/src/sql-models/setting.js new file mode 100644 index 00000000..2c4b710d --- /dev/null +++ b/packages/lambda/src/sql-models/setting.js @@ -0,0 +1,20 @@ +'use strict'; + +const { sequelize, Sequelize } = require('./index') + +const Setting = sequelize.define('Setting', { + key: Sequelize.DataTypes.STRING, + value: Sequelize.DataTypes.STRING +}); + +//class Setting extends Sequelize.Model {} +// +//Setting.init({ +// key: Sequelize.DataTypes.STRING, +// value: Sequelize.DataTypes.STRING +//}, { +// sequelize, +// modelName: 'Setting' +//}); + +module.exports = Setting; From ed510ebc392eca1a49b995e0070f857be2d31392 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Mon, 10 Aug 2020 08:36:42 -0500 Subject: [PATCH 034/140] WIP --- packages/cloudformation/templates/givesource-aurora.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index fb453ef5..3ac51b60 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -65,7 +65,7 @@ Resources: Name: !Sub ${AWS::StackName}-AdminUserSecret Description: Givesource database auto-generated admin user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: '"@/\' @@ -81,7 +81,7 @@ Resources: Name: !Sub ${AWS::StackName}-MaintenanceUserSecret Description: Givesource database auto-generated maintenance user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludePunctuation: true @@ -97,7 +97,7 @@ Resources: Name: !Sub ${AWS::StackName}-ReadwriteUserSecret Description: Givesource database auto-generated readwrite user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludePunctuation: true @@ -113,7 +113,7 @@ Resources: Name: !Sub ${AWS::StackName}-ReadonlyUserSecret Description: Givesource database auto-generated readonly user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludePunctuation: true From 3ae84f88ca2452e3121759da32ae011d3843c84b Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Mon, 10 Aug 2020 09:13:24 -0500 Subject: [PATCH 035/140] WIP --- .../templates/givesource-aurora.yml | 25 ++----------------- .../cloudformation/templates/givesource.yml | 6 +++++ 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 3ac51b60..f1e95439 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -280,32 +280,11 @@ Resources: ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn DependsOn: BootstrapDatabaseLambdaLambdaInvoker Outputs: - StackName: - Description: Aurora Stack Name - Value: !Ref AWS::StackName - Export: - Name: !Sub ${AWS::StackName}-StackName - - ReadwriteUserSecretId: - Description: Secret Id for the readwrite user + ReadwriteUserSecret: Value: !Sub ${AWS::StackName}-ReadwriteUserSecret - Export: - Name: !Sub ${AWS::StackName}-ReadwriteUserSecretId - - ReadonlyUserSecretId: - Description: Secret Id for the readonly user + ReadonlyUserSecret: Value: !Sub ${AWS::StackName}-ReadonlyUserSecret - Export: - Name: !Sub ${AWS::StackName}-UserSecretId - DatabaseClusterArn: - Description: Aurora Cluster ARN Value: !Ref RDSCluster - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterArn - DatabaseEndpoint: - Description: Aurora Database Endpoint Value: !GetAtt RDSCluster.Endpoint.Address - Export: - Name: !Sub ${AWS::StackName}-DatabaseEndpoint diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 50cc7f04..0bd118fd 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -765,6 +765,12 @@ Outputs: LambdaRoleArn: Value: !GetAtt LambdaRole.Arn + DatabaseReadwriteSecret: + Value: !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecret + + DatabaseReadonlySecret: + Value: !GetAtt AuroraDbStack.Outputs.ReadonlyUserSecret + PublicPagesCloudFrontDistribution: Value: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDistribution From ef79c931bf056590c166ecbdec7772e9783160bd Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Mon, 10 Aug 2020 12:45:21 -0500 Subject: [PATCH 036/140] WIP --- .../cloudformation/templates/givesource.yml | 9 +++ packages/lambda/src/aws/cloudformation.js | 39 ++++++++++ packages/lambda/src/sql-models/connect.js | 77 +++++++++++++++++++ packages/lambda/src/sql-models/index.js | 38 --------- packages/lambda/src/sql-models/setting.js | 4 +- 5 files changed, 128 insertions(+), 39 deletions(-) create mode 100644 packages/lambda/src/aws/cloudformation.js create mode 100644 packages/lambda/src/sql-models/connect.js delete mode 100644 packages/lambda/src/sql-models/index.js diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 0bd118fd..12d1545d 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -304,6 +304,14 @@ Resources: - ssm:PutParameter Resource: '*' + # TODO: Create a different policy for this + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: '*' +# Resource: +# - !Ref ReadonlyUserSecret + LambdaRole: Type: AWS::IAM::Role Properties: @@ -316,6 +324,7 @@ Resources: - lambda.amazonaws.com - edgelambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref ApiGatewayManagedPolicy - !Ref CloudFormationManagedPolicy - !Ref CloudWatchLogsManagedPolicy diff --git a/packages/lambda/src/aws/cloudformation.js b/packages/lambda/src/aws/cloudformation.js new file mode 100644 index 00000000..3b7ac0c8 --- /dev/null +++ b/packages/lambda/src/aws/cloudformation.js @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const AWS = require('aws-sdk'); + +/** + * CloudFormation constructor + * + * @constructor + */ +function CloudFormation() { +} + +/** + * Get an output from a cloud formation stack + * + * @param region + * @param stackName + * @returns {Promise} + */ +CloudFormation.prototype.describeStacks = (region, stackName) => { + const cloudFormation = new AWS.CloudFormation({region: region}); + return cloudFormation.describeStacks({StackName: stackName}).promise(); +}; + +module.exports = CloudFormation; diff --git a/packages/lambda/src/sql-models/connect.js b/packages/lambda/src/sql-models/connect.js new file mode 100644 index 00000000..3fc51dec --- /dev/null +++ b/packages/lambda/src/sql-models/connect.js @@ -0,0 +1,77 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const CloudFormation = require('./../aws/cloudformation'); +const SecretsManager = require('./../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); + +console.log("IN CONNECT"); + +function init() { + try { + console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); + + const cloudFormation = new CloudFormation(); + return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { + const stack = stacks.Stacks[0]; + const secretId = stack.Outputs.find(it => it.OutputKey === 'DatabaseReadonlySecret').OutputValue; + console.log("SECRET ID IS " + secretId); + const secretsManager = new SecretsManager(); + return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); + }).then(function (secret) { + console.log("SECRET IS " + secret); + console.log(secret); + //const readonlySecret = JSON.parse(secret.SecretString); + return new Sequelize({ + //host: readonlySecret.host, + //username: readonlySecret.username, + //password: readonlySecret.password, + //database: readonlySecret.database, + //port: readonlySecret.port, + host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } + }); + }); + } catch (error) { + console.log("ERROR"); + console.log(error); + throw error; + } +} + +console.log("INIT IS"); +console.log(init()); + +//const sequelize = init(); +const sequelize = new Sequelize({ + //host: readonlySecret.host, + //username: readonlySecret.username, + //password: readonlySecret.password, + //database: readonlySecret.database, + //port: readonlySecret.port, + host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } +}); +//console.log("FROM INIT, SEQUELIZE IS "); +//console.log(sequelize); +module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; diff --git a/packages/lambda/src/sql-models/index.js b/packages/lambda/src/sql-models/index.js deleted file mode 100644 index b64ed821..00000000 --- a/packages/lambda/src/sql-models/index.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const SecretsManager = require('./../aws/secretsManager'); -const mysql2 = require('mysql2'); -const Sequelize = require('sequelize'); -const basename = path.basename(__filename); -const env = process.env.NODE_ENV || 'development'; -const db = {}; -console.log("IN INDEX.js"); - -const secretsManager = new SecretsManager(); -//return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID); -//console.log(secret); -//const readonlySecret = JSON.parse(secret.SecretString); -const sequelize = new Sequelize({ - //host: readonlySecret.host, - //username: readonlySecret.username, - //password: readonlySecret.password, - //port: readonlySecret.port, - host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } -}); - -db.sequelize = sequelize; -db.Sequelize = Sequelize; - -module.exports = db; diff --git a/packages/lambda/src/sql-models/setting.js b/packages/lambda/src/sql-models/setting.js index 2c4b710d..132d8930 100644 --- a/packages/lambda/src/sql-models/setting.js +++ b/packages/lambda/src/sql-models/setting.js @@ -1,6 +1,8 @@ 'use strict'; -const { sequelize, Sequelize } = require('./index') +const { sequelize, Sequelize } = require('./connect') +//console.log("IN SETTINGS, SEQUELIZE IS "); +//console.log(sequelize); const Setting = sequelize.define('Setting', { key: Sequelize.DataTypes.STRING, From 40ec1594c6e9b8bb1f9ad2d72aa33dd9dc17847d Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Mon, 10 Aug 2020 12:54:09 -0500 Subject: [PATCH 037/140] WIP --- packages/lambda/src/sql-models/connect.js | 78 +++++++++-------------- packages/lambda/src/sql-models/setting.js | 10 --- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/packages/lambda/src/sql-models/connect.js b/packages/lambda/src/sql-models/connect.js index 3fc51dec..67c922dc 100644 --- a/packages/lambda/src/sql-models/connect.js +++ b/packages/lambda/src/sql-models/connect.js @@ -8,58 +8,42 @@ const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); console.log("IN CONNECT"); - function init() { - try { - console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); + console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); - const cloudFormation = new CloudFormation(); - return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { - const stack = stacks.Stacks[0]; - const secretId = stack.Outputs.find(it => it.OutputKey === 'DatabaseReadonlySecret').OutputValue; - console.log("SECRET ID IS " + secretId); - const secretsManager = new SecretsManager(); - return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); - }).then(function (secret) { - console.log("SECRET IS " + secret); - console.log(secret); - //const readonlySecret = JSON.parse(secret.SecretString); - return new Sequelize({ - //host: readonlySecret.host, - //username: readonlySecret.username, - //password: readonlySecret.password, - //database: readonlySecret.database, - //port: readonlySecret.port, - host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } - }); + const cloudFormation = new CloudFormation(); + cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { + const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadonlySecret').OutputValue; + const secretsManager = new SecretsManager(); + return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); + }).then(function (secret) { + console.log("SECRET IS " + secret); + console.log(secret); + const readonlySecret = JSON.parse(secret.SecretString); + return new Sequelize({ + host: readonlySecret.host, + username: readonlySecret.username, + password: readonlySecret.password, + database: readonlySecret.database, + port: readonlySecret.port, + //host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + //username: 'readonly', + //password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', + //database: 'givesource', + //port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } }); - } catch (error) { - console.log("ERROR"); - console.log(error); - throw error; - } + }); } - -console.log("INIT IS"); -console.log(init()); - //const sequelize = init(); +//module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; + const sequelize = new Sequelize({ - //host: readonlySecret.host, - //username: readonlySecret.username, - //password: readonlySecret.password, - //database: readonlySecret.database, - //port: readonlySecret.port, host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', username: 'readonly', password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', @@ -72,6 +56,4 @@ const sequelize = new Sequelize({ ssl: 'Amazon RDS' } }); -//console.log("FROM INIT, SEQUELIZE IS "); -//console.log(sequelize); module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; diff --git a/packages/lambda/src/sql-models/setting.js b/packages/lambda/src/sql-models/setting.js index 132d8930..1a945884 100644 --- a/packages/lambda/src/sql-models/setting.js +++ b/packages/lambda/src/sql-models/setting.js @@ -9,14 +9,4 @@ const Setting = sequelize.define('Setting', { value: Sequelize.DataTypes.STRING }); -//class Setting extends Sequelize.Model {} -// -//Setting.init({ -// key: Sequelize.DataTypes.STRING, -// value: Sequelize.DataTypes.STRING -//}, { -// sequelize, -// modelName: 'Setting' -//}); - module.exports = Setting; From 4a38404a86f8b536635355d7297e51f46ae30628 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 12 Aug 2020 11:37:10 -0500 Subject: [PATCH 038/140] GD-1640: Update the settings repository (moved models, trying to get setting.js to connect with findAll()) --- packages/lambda/bin/delete-test-payments.js | 2 +- packages/lambda/package-lock.json | 398 ++++++++++++++++++ packages/lambda/package.json | 1 + .../src/api/adminRegisterNonprofit/index.js | 4 +- .../lambda/src/api/deleteContents/index.js | 2 +- packages/lambda/src/api/deleteFiles/index.js | 2 +- .../lambda/src/api/deleteMetrics/index.js | 2 +- .../api/deleteNonprofitDonationTiers/index.js | 2 +- .../lambda/src/api/deleteSettings/index.js | 2 +- .../lambda/src/api/deleteSponsors/index.js | 2 +- packages/lambda/src/api/getSettings/index.js | 13 +- packages/lambda/src/api/patchContent/index.js | 2 +- .../lambda/src/api/patchContents/index.js | 2 +- .../lambda/src/api/patchDonation/index.js | 2 +- packages/lambda/src/api/patchMessage/index.js | 2 +- packages/lambda/src/api/patchMetrics/index.js | 2 +- .../lambda/src/api/patchNonprofit/index.js | 2 +- .../src/api/patchNonprofitDonation/index.js | 2 +- .../api/patchNonprofitDonationTiers/index.js | 2 +- .../src/api/patchNonprofitSlide/index.js | 2 +- .../src/api/patchNonprofitSlides/index.js | 2 +- .../src/api/patchNonprofitStatus/index.js | 2 +- .../src/api/patchPaymentTransaction/index.js | 2 +- packages/lambda/src/api/patchSetting/index.js | 2 +- .../lambda/src/api/patchSettings/index.js | 2 +- packages/lambda/src/api/patchSponsor/index.js | 2 +- .../lambda/src/api/patchSponsorTier/index.js | 2 +- .../lambda/src/api/patchSponsorTiers/index.js | 2 +- .../lambda/src/api/patchSponsors/index.js | 2 +- packages/lambda/src/api/patchUser/index.js | 2 +- packages/lambda/src/api/postContent/index.js | 2 +- packages/lambda/src/api/postDonation/index.js | 2 +- packages/lambda/src/api/postDonor/index.js | 2 +- packages/lambda/src/api/postFile/index.js | 2 +- packages/lambda/src/api/postMessage/index.js | 2 +- .../lambda/src/api/postNonprofit/index.js | 2 +- .../src/api/postNonprofitDonation/index.js | 2 +- .../api/postNonprofitDonationTier/index.js | 2 +- .../src/api/postNonprofitReport/index.js | 2 +- .../src/api/postNonprofitSlide/index.js | 2 +- .../lambda/src/api/postNonprofitUser/index.js | 2 +- .../src/api/postPaymentTransaction/index.js | 2 +- packages/lambda/src/api/postReport/index.js | 2 +- packages/lambda/src/api/postSetting/index.js | 2 +- packages/lambda/src/api/postSponsor/index.js | 2 +- .../lambda/src/api/postSponsorTier/index.js | 2 +- packages/lambda/src/api/postUser/index.js | 2 +- .../lambda/src/api/processDonations/index.js | 6 +- .../lambda/src/api/registerNonprofit/index.js | 4 +- .../api/resendUserEmailVerification/index.js | 2 +- .../src/custom/cognitoCreateUser/index.js | 2 +- .../custom/generateDonationsReceipt/index.js | 6 +- .../lambda/src/custom/generateReport/index.js | 6 +- .../src/custom/metricAddAmount/index.js | 2 +- .../src/custom/metricMaxAmount/index.js | 2 +- .../lambda/src/custom/saveSettings/index.js | 2 +- .../sendDonationNotificationEmail/index.js | 2 +- .../src/{models => dynamo-models}/content.js | 0 .../src/{models => dynamo-models}/donation.js | 0 .../src/{models => dynamo-models}/donor.js | 0 .../src/{models => dynamo-models}/file.js | 0 .../src/{models => dynamo-models}/message.js | 0 .../src/{models => dynamo-models}/metric.js | 0 .../src/{models => dynamo-models}/model.js | 0 .../{models => dynamo-models}/nonprofit.js | 0 .../nonprofitDonationTier.js | 0 .../nonprofitSlide.js | 0 .../paymentTransaction.js | 0 .../src/{models => dynamo-models}/report.js | 0 .../src/{models => dynamo-models}/sponsor.js | 0 .../{models => dynamo-models}/sponsorTier.js | 0 .../src/{models => dynamo-models}/user.js | 0 packages/lambda/src/helpers/generator.js | 2 +- packages/lambda/src/models/connect.js | 43 ++ packages/lambda/src/models/index.js | 46 ++ packages/lambda/src/models/setting.js | 10 + packages/lambda/src/repositories/contents.js | 2 +- packages/lambda/src/repositories/donations.js | 2 +- packages/lambda/src/repositories/donors.js | 2 +- packages/lambda/src/repositories/files.js | 2 +- packages/lambda/src/repositories/messages.js | 2 +- packages/lambda/src/repositories/metrics.js | 2 +- .../repositories/nonprofitDonationTiers.js | 2 +- .../src/repositories/nonprofitDonations.js | 2 +- .../src/repositories/nonprofitReports.js | 2 +- .../src/repositories/nonprofitSlides.js | 2 +- .../lambda/src/repositories/nonprofitUsers.js | 2 +- .../lambda/src/repositories/nonprofits.js | 2 +- .../src/repositories/paymentTransactions.js | 2 +- packages/lambda/src/repositories/reports.js | 2 +- .../lambda/src/repositories/repository.js | 2 +- packages/lambda/src/repositories/settings.js | 31 +- .../lambda/src/repositories/sponsorTiers.js | 2 +- packages/lambda/src/repositories/sponsors.js | 2 +- packages/lambda/src/repositories/users.js | 2 +- packages/lambda/src/sql-models/connect.js | 59 --- packages/lambda/src/sql-models/setting.js | 12 - packages/lambda/test/models/donation.js | 4 +- packages/lambda/test/models/donor.js | 4 +- packages/lambda/test/models/file.js | 4 +- packages/lambda/test/models/message.js | 4 +- packages/lambda/test/models/metric.js | 4 +- packages/lambda/test/models/model.js | 2 +- packages/lambda/test/models/nonprofit.js | 4 +- packages/lambda/test/models/nonprofitSlide.js | 4 +- .../lambda/test/models/paymentTransaction.js | 4 +- packages/lambda/test/models/report.js | 4 +- packages/lambda/test/models/setting.js | 4 +- packages/lambda/test/models/sponsor.js | 4 +- packages/lambda/test/models/sponsorTier.js | 4 +- packages/lambda/test/models/user.js | 4 +- .../lambda/test/repositories/donations.js | 2 +- packages/lambda/test/repositories/donors.js | 2 +- packages/lambda/test/repositories/messages.js | 2 +- packages/lambda/test/repositories/metrics.js | 2 +- .../test/repositories/nonprofitSlides.js | 2 +- .../lambda/test/repositories/nonprofits.js | 2 +- .../test/repositories/paymentTransactions.js | 2 +- packages/lambda/test/repositories/reports.js | 2 +- packages/lambda/test/repositories/settings.js | 2 +- .../lambda/test/repositories/sponsorTiers.js | 2 +- packages/lambda/test/repositories/sponsors.js | 2 +- packages/lambda/test/repositories/users.js | 2 +- 123 files changed, 627 insertions(+), 226 deletions(-) rename packages/lambda/src/{models => dynamo-models}/content.js (100%) rename packages/lambda/src/{models => dynamo-models}/donation.js (100%) rename packages/lambda/src/{models => dynamo-models}/donor.js (100%) rename packages/lambda/src/{models => dynamo-models}/file.js (100%) rename packages/lambda/src/{models => dynamo-models}/message.js (100%) rename packages/lambda/src/{models => dynamo-models}/metric.js (100%) rename packages/lambda/src/{models => dynamo-models}/model.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofit.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofitDonationTier.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofitSlide.js (100%) rename packages/lambda/src/{models => dynamo-models}/paymentTransaction.js (100%) rename packages/lambda/src/{models => dynamo-models}/report.js (100%) rename packages/lambda/src/{models => dynamo-models}/sponsor.js (100%) rename packages/lambda/src/{models => dynamo-models}/sponsorTier.js (100%) rename packages/lambda/src/{models => dynamo-models}/user.js (100%) create mode 100644 packages/lambda/src/models/connect.js create mode 100644 packages/lambda/src/models/index.js create mode 100644 packages/lambda/src/models/setting.js delete mode 100644 packages/lambda/src/sql-models/connect.js delete mode 100644 packages/lambda/src/sql-models/setting.js diff --git a/packages/lambda/bin/delete-test-payments.js b/packages/lambda/bin/delete-test-payments.js index 7bfa2146..3db92fd9 100644 --- a/packages/lambda/bin/delete-test-payments.js +++ b/packages/lambda/bin/delete-test-payments.js @@ -17,7 +17,7 @@ require('./config/bootstrap').bootstrap(); const config = require('config'); -const Donation = require('./../src/models/donation'); +const Donation = require('./../src/dynamo-models/donation'); const DonationsRepository = require('./../src/repositories/donations'); const inquirer = require('inquirer'); const QueryBuilder = require('./../src/aws/queryBuilder'); diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index a7e195a3..b9b31046 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -320,6 +320,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", @@ -1178,6 +1184,20 @@ } } }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1339,6 +1359,16 @@ } } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -1503,6 +1533,16 @@ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1683,6 +1723,42 @@ "safe-buffer": "^5.0.1" } }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -1748,12 +1824,56 @@ "is-arrayish": "^0.2.1" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1796,6 +1916,16 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -1861,6 +1991,23 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2207,6 +2354,17 @@ "readable-stream": "^2.0.0" } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -3185,6 +3343,12 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, "inquirer": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz", @@ -3694,6 +3858,41 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, + "js-beautify": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.11.0.tgz", + "integrity": "sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A==", + "dev": true, + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "~1.0.3", + "nopt": "^4.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -3782,6 +3981,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonwebtoken": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", @@ -4032,6 +4240,15 @@ "yallist": "^3.0.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4102,6 +4319,22 @@ "p-is-promise": "^1.1.0" } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -4475,6 +4708,12 @@ "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4554,6 +4793,16 @@ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -4867,6 +5116,16 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -5229,6 +5488,12 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -5729,6 +5994,111 @@ } } }, + "sequelize-cli": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", + "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", + "dev": true, + "requires": { + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.3.0", + "yargs": "^13.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -5794,6 +6164,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6473,6 +6849,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "title-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", @@ -6608,6 +6994,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-detect": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", @@ -6688,6 +7080,12 @@ "imurmurhash": "^0.1.4" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 42bf4e59..28a927d7 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -61,6 +61,7 @@ "randomstring": "^1.1.5", "raw-loader": "^0.5.1", "request": "^2.88.0", + "sequelize-cli": "^6.2.0", "sinon": "^2.3.6", "slug": "^0.9.3", "uuid-validate": "0.0.2", diff --git a/packages/lambda/src/api/adminRegisterNonprofit/index.js b/packages/lambda/src/api/adminRegisterNonprofit/index.js index 78bcdeda..a1983f1a 100644 --- a/packages/lambda/src/api/adminRegisterNonprofit/index.js +++ b/packages/lambda/src/api/adminRegisterNonprofit/index.js @@ -17,11 +17,11 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/deleteContents/index.js b/packages/lambda/src/api/deleteContents/index.js index d8e4d444..e96fc421 100644 --- a/packages/lambda/src/api/deleteContents/index.js +++ b/packages/lambda/src/api/deleteContents/index.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentHelper = require('./../../helpers/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); diff --git a/packages/lambda/src/api/deleteFiles/index.js b/packages/lambda/src/api/deleteFiles/index.js index 5615c9fb..da7baa05 100644 --- a/packages/lambda/src/api/deleteFiles/index.js +++ b/packages/lambda/src/api/deleteFiles/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/deleteMetrics/index.js b/packages/lambda/src/api/deleteMetrics/index.js index 2954f32f..286dd743 100644 --- a/packages/lambda/src/api/deleteMetrics/index.js +++ b/packages/lambda/src/api/deleteMetrics/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js b/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js index 3a810b6b..51fb0634 100644 --- a/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js +++ b/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index f2e79e73..d00c3f9a 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../sql-models/setting'); +const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index f05a865d..4a154a5c 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/getSettings/index.js b/packages/lambda/src/api/getSettings/index.js index 6be7d4cb..07d7cb5e 100644 --- a/packages/lambda/src/api/getSettings/index.js +++ b/packages/lambda/src/api/getSettings/index.js @@ -17,6 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); const SettingsRepository = require('./../../repositories/settings'); +const Setting = require('./../../models/index').Setting; exports.handle = function (event, context, callback) { const repository = new SettingsRepository(); @@ -26,18 +27,12 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { console.log("KEYS ARE "); console.log(keys); - if (keys.length) { - return repository.batchGet(keys); - } else { - return repository.getAll(); - } + console.log(Setting); /*DM: Debug */ + return Setting.findAll(); }).then(function (settings) { console.log("SETTINGS ARE "); console.log(settings); - const results = settings.map(function (setting) { - return setting.findAll(); - }); - callback(null, results); + callback(null, settings); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/patchContent/index.js b/packages/lambda/src/api/patchContent/index.js index 6a36e6ed..82f1af9b 100644 --- a/packages/lambda/src/api/patchContent/index.js +++ b/packages/lambda/src/api/patchContent/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/patchContents/index.js b/packages/lambda/src/api/patchContents/index.js index da717251..51de2d75 100644 --- a/packages/lambda/src/api/patchContents/index.js +++ b/packages/lambda/src/api/patchContents/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/patchDonation/index.js b/packages/lambda/src/api/patchDonation/index.js index 532489b0..dd8421c2 100644 --- a/packages/lambda/src/api/patchDonation/index.js +++ b/packages/lambda/src/api/patchDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchMessage/index.js b/packages/lambda/src/api/patchMessage/index.js index 25bc2d0b..bfbf54e2 100644 --- a/packages/lambda/src/api/patchMessage/index.js +++ b/packages/lambda/src/api/patchMessage/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Message = require('./../../models/message'); +const Message = require('./../../dynamo-models/message'); const MessagesRepository = require('./../../repositories/messages'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchMetrics/index.js b/packages/lambda/src/api/patchMetrics/index.js index 27d1f250..67ae8172 100644 --- a/packages/lambda/src/api/patchMetrics/index.js +++ b/packages/lambda/src/api/patchMetrics/index.js @@ -16,7 +16,7 @@ const _ = require('lodash'); const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchNonprofit/index.js b/packages/lambda/src/api/patchNonprofit/index.js index aa2220e9..5e80718d 100644 --- a/packages/lambda/src/api/patchNonprofit/index.js +++ b/packages/lambda/src/api/patchNonprofit/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitDonation/index.js b/packages/lambda/src/api/patchNonprofitDonation/index.js index 90ac4ffc..43c02cbc 100644 --- a/packages/lambda/src/api/patchNonprofitDonation/index.js +++ b/packages/lambda/src/api/patchNonprofitDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const HttpException = require('./../../exceptions/http'); const NonprofitDonationsRepository = require('./../../repositories/nonprofitDonations'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitDonationTiers/index.js b/packages/lambda/src/api/patchNonprofitDonationTiers/index.js index 40a2be5b..374bd356 100644 --- a/packages/lambda/src/api/patchNonprofitDonationTiers/index.js +++ b/packages/lambda/src/api/patchNonprofitDonationTiers/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitSlide/index.js b/packages/lambda/src/api/patchNonprofitSlide/index.js index c5cce02d..1bb09675 100644 --- a/packages/lambda/src/api/patchNonprofitSlide/index.js +++ b/packages/lambda/src/api/patchNonprofitSlide/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitSlides/index.js b/packages/lambda/src/api/patchNonprofitSlides/index.js index e89cd866..40977bd6 100644 --- a/packages/lambda/src/api/patchNonprofitSlides/index.js +++ b/packages/lambda/src/api/patchNonprofitSlides/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitStatus/index.js b/packages/lambda/src/api/patchNonprofitStatus/index.js index f441109e..757525b0 100644 --- a/packages/lambda/src/api/patchNonprofitStatus/index.js +++ b/packages/lambda/src/api/patchNonprofitStatus/index.js @@ -19,7 +19,7 @@ const HttpException = require('./../../exceptions/http'); const InvalidInputException = require('./../../exceptions/invalidInput'); const InvalidStatusException = require('./../../exceptions/invalidStatus'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); diff --git a/packages/lambda/src/api/patchPaymentTransaction/index.js b/packages/lambda/src/api/patchPaymentTransaction/index.js index a476adbd..5749fe40 100644 --- a/packages/lambda/src/api/patchPaymentTransaction/index.js +++ b/packages/lambda/src/api/patchPaymentTransaction/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSetting/index.js b/packages/lambda/src/api/patchSetting/index.js index e41ad722..9f632055 100644 --- a/packages/lambda/src/api/patchSetting/index.js +++ b/packages/lambda/src/api/patchSetting/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../sql-models/setting'); +const Setting = require('./../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index 78a6adbd..627b8559 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -18,7 +18,7 @@ const _ = require('lodash'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../sql-models/setting'); +const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); diff --git a/packages/lambda/src/api/patchSponsor/index.js b/packages/lambda/src/api/patchSponsor/index.js index 8df74646..00aba9f8 100644 --- a/packages/lambda/src/api/patchSponsor/index.js +++ b/packages/lambda/src/api/patchSponsor/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsorTier/index.js b/packages/lambda/src/api/patchSponsorTier/index.js index af68c281..6fdef97a 100644 --- a/packages/lambda/src/api/patchSponsorTier/index.js +++ b/packages/lambda/src/api/patchSponsorTier/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsorTiers/index.js b/packages/lambda/src/api/patchSponsorTiers/index.js index bfe51d1c..b8be51b5 100644 --- a/packages/lambda/src/api/patchSponsorTiers/index.js +++ b/packages/lambda/src/api/patchSponsorTiers/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsors/index.js b/packages/lambda/src/api/patchSponsors/index.js index bdd46761..3d4da37d 100644 --- a/packages/lambda/src/api/patchSponsors/index.js +++ b/packages/lambda/src/api/patchSponsors/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchUser/index.js b/packages/lambda/src/api/patchUser/index.js index acc89c7e..c5f15d65 100644 --- a/packages/lambda/src/api/patchUser/index.js +++ b/packages/lambda/src/api/patchUser/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserResourceMiddleware = require('./../../middleware/userResource'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/postContent/index.js b/packages/lambda/src/api/postContent/index.js index 0c5a87eb..38b0f8de 100644 --- a/packages/lambda/src/api/postContent/index.js +++ b/packages/lambda/src/api/postContent/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postDonation/index.js b/packages/lambda/src/api/postDonation/index.js index 98d2939f..747ec136 100644 --- a/packages/lambda/src/api/postDonation/index.js +++ b/packages/lambda/src/api/postDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postDonor/index.js b/packages/lambda/src/api/postDonor/index.js index f322c26d..483ff6fa 100644 --- a/packages/lambda/src/api/postDonor/index.js +++ b/packages/lambda/src/api/postDonor/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postFile/index.js b/packages/lambda/src/api/postFile/index.js index df8e0c5d..bf4656d5 100644 --- a/packages/lambda/src/api/postFile/index.js +++ b/packages/lambda/src/api/postFile/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postMessage/index.js b/packages/lambda/src/api/postMessage/index.js index 50b99771..4e52477f 100644 --- a/packages/lambda/src/api/postMessage/index.js +++ b/packages/lambda/src/api/postMessage/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Message = require('./../../models/message'); +const Message = require('./../../dynamo-models/message'); const MessagesRepository = require('./../../repositories/messages'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofit/index.js b/packages/lambda/src/api/postNonprofit/index.js index 3b8e2940..7742b24d 100644 --- a/packages/lambda/src/api/postNonprofit/index.js +++ b/packages/lambda/src/api/postNonprofit/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postNonprofitDonation/index.js b/packages/lambda/src/api/postNonprofitDonation/index.js index 2f0ff4bc..7a138fd3 100644 --- a/packages/lambda/src/api/postNonprofitDonation/index.js +++ b/packages/lambda/src/api/postNonprofitDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postNonprofitDonationTier/index.js b/packages/lambda/src/api/postNonprofitDonationTier/index.js index 807df889..ec441bc9 100644 --- a/packages/lambda/src/api/postNonprofitDonationTier/index.js +++ b/packages/lambda/src/api/postNonprofitDonationTier/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitReport/index.js b/packages/lambda/src/api/postNonprofitReport/index.js index ccff3a21..39fee218 100644 --- a/packages/lambda/src/api/postNonprofitReport/index.js +++ b/packages/lambda/src/api/postNonprofitReport/index.js @@ -18,7 +18,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitReportsRepository = require('./../../repositories/nonprofitReports'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitSlide/index.js b/packages/lambda/src/api/postNonprofitSlide/index.js index faecf3c7..ac861c2f 100644 --- a/packages/lambda/src/api/postNonprofitSlide/index.js +++ b/packages/lambda/src/api/postNonprofitSlide/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitUser/index.js b/packages/lambda/src/api/postNonprofitUser/index.js index 4d00788c..2fde0036 100644 --- a/packages/lambda/src/api/postNonprofitUser/index.js +++ b/packages/lambda/src/api/postNonprofitUser/index.js @@ -19,7 +19,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/api/postPaymentTransaction/index.js b/packages/lambda/src/api/postPaymentTransaction/index.js index be0bdc05..c5f4624e 100644 --- a/packages/lambda/src/api/postPaymentTransaction/index.js +++ b/packages/lambda/src/api/postPaymentTransaction/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postReport/index.js b/packages/lambda/src/api/postReport/index.js index b13b31b7..74aeb990 100644 --- a/packages/lambda/src/api/postReport/index.js +++ b/packages/lambda/src/api/postReport/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const ReportsRepository = require('./../../repositories/reports'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index 9e5cb1f3..f6b6603f 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -18,7 +18,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const ResourceAlreadyExistsException = require('./../../exceptions/resourceAlreadyExists'); -const Setting = require('./../../sql-models/setting'); +const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); diff --git a/packages/lambda/src/api/postSponsor/index.js b/packages/lambda/src/api/postSponsor/index.js index c233c420..35541b53 100644 --- a/packages/lambda/src/api/postSponsor/index.js +++ b/packages/lambda/src/api/postSponsor/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postSponsorTier/index.js b/packages/lambda/src/api/postSponsorTier/index.js index 0c00f1bd..af716e2f 100644 --- a/packages/lambda/src/api/postSponsorTier/index.js +++ b/packages/lambda/src/api/postSponsorTier/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postUser/index.js b/packages/lambda/src/api/postUser/index.js index d140c288..ae8ba2bb 100644 --- a/packages/lambda/src/api/postUser/index.js +++ b/packages/lambda/src/api/postUser/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/processDonations/index.js b/packages/lambda/src/api/processDonations/index.js index c5c7892c..69c19748 100644 --- a/packages/lambda/src/api/processDonations/index.js +++ b/packages/lambda/src/api/processDonations/index.js @@ -16,15 +16,15 @@ const _ = require('lodash'); const axios = require('axios'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const DonationsRepository = require('./../../repositories/donations'); -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const NonprofitsRepository = require('./../../repositories/nonprofits'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const SettingHelper = require('./../../helpers/setting'); diff --git a/packages/lambda/src/api/registerNonprofit/index.js b/packages/lambda/src/api/registerNonprofit/index.js index 9eb8d403..c4e52ed2 100644 --- a/packages/lambda/src/api/registerNonprofit/index.js +++ b/packages/lambda/src/api/registerNonprofit/index.js @@ -16,11 +16,11 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/api/resendUserEmailVerification/index.js b/packages/lambda/src/api/resendUserEmailVerification/index.js index 8303d26f..9eae74cd 100644 --- a/packages/lambda/src/api/resendUserEmailVerification/index.js +++ b/packages/lambda/src/api/resendUserEmailVerification/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/custom/cognitoCreateUser/index.js b/packages/lambda/src/custom/cognitoCreateUser/index.js index 3a1189ed..694e572a 100644 --- a/packages/lambda/src/custom/cognitoCreateUser/index.js +++ b/packages/lambda/src/custom/cognitoCreateUser/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/custom/generateDonationsReceipt/index.js b/packages/lambda/src/custom/generateDonationsReceipt/index.js index 3b2e1ea8..afa4e300 100644 --- a/packages/lambda/src/custom/generateDonationsReceipt/index.js +++ b/packages/lambda/src/custom/generateDonationsReceipt/index.js @@ -15,13 +15,13 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const QueryBuilder = require('./../../aws/queryBuilder'); const RenderHelper = require('./../../helpers/render'); diff --git a/packages/lambda/src/custom/generateReport/index.js b/packages/lambda/src/custom/generateReport/index.js index d09a6929..0be30728 100644 --- a/packages/lambda/src/custom/generateReport/index.js +++ b/packages/lambda/src/custom/generateReport/index.js @@ -15,15 +15,15 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const DonationsRepository = require('./../../repositories/donations'); -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const json2csv = require('json2csv'); const NonprofitDonationsRepository = require('./../../repositories/nonprofitDonations'); const QueryBuilder = require('./../../aws/queryBuilder'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const ReportsRepository = require('./../../repositories/reports'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/metricAddAmount/index.js b/packages/lambda/src/custom/metricAddAmount/index.js index 5e6023e5..8ebc1dc0 100644 --- a/packages/lambda/src/custom/metricAddAmount/index.js +++ b/packages/lambda/src/custom/metricAddAmount/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/metricMaxAmount/index.js b/packages/lambda/src/custom/metricMaxAmount/index.js index 6526e55d..aa876d7c 100644 --- a/packages/lambda/src/custom/metricMaxAmount/index.js +++ b/packages/lambda/src/custom/metricMaxAmount/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index 1ee4f78d..cc0b9c94 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -17,7 +17,7 @@ const _ = require('lodash'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const Setting = require('./../../sql-models/setting'); +const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const S3 = require('./../../aws/s3'); diff --git a/packages/lambda/src/custom/sendDonationNotificationEmail/index.js b/packages/lambda/src/custom/sendDonationNotificationEmail/index.js index 8db2a997..983eacb8 100644 --- a/packages/lambda/src/custom/sendDonationNotificationEmail/index.js +++ b/packages/lambda/src/custom/sendDonationNotificationEmail/index.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const EmailHelper = require('./../../helpers/email'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); diff --git a/packages/lambda/src/models/content.js b/packages/lambda/src/dynamo-models/content.js similarity index 100% rename from packages/lambda/src/models/content.js rename to packages/lambda/src/dynamo-models/content.js diff --git a/packages/lambda/src/models/donation.js b/packages/lambda/src/dynamo-models/donation.js similarity index 100% rename from packages/lambda/src/models/donation.js rename to packages/lambda/src/dynamo-models/donation.js diff --git a/packages/lambda/src/models/donor.js b/packages/lambda/src/dynamo-models/donor.js similarity index 100% rename from packages/lambda/src/models/donor.js rename to packages/lambda/src/dynamo-models/donor.js diff --git a/packages/lambda/src/models/file.js b/packages/lambda/src/dynamo-models/file.js similarity index 100% rename from packages/lambda/src/models/file.js rename to packages/lambda/src/dynamo-models/file.js diff --git a/packages/lambda/src/models/message.js b/packages/lambda/src/dynamo-models/message.js similarity index 100% rename from packages/lambda/src/models/message.js rename to packages/lambda/src/dynamo-models/message.js diff --git a/packages/lambda/src/models/metric.js b/packages/lambda/src/dynamo-models/metric.js similarity index 100% rename from packages/lambda/src/models/metric.js rename to packages/lambda/src/dynamo-models/metric.js diff --git a/packages/lambda/src/models/model.js b/packages/lambda/src/dynamo-models/model.js similarity index 100% rename from packages/lambda/src/models/model.js rename to packages/lambda/src/dynamo-models/model.js diff --git a/packages/lambda/src/models/nonprofit.js b/packages/lambda/src/dynamo-models/nonprofit.js similarity index 100% rename from packages/lambda/src/models/nonprofit.js rename to packages/lambda/src/dynamo-models/nonprofit.js diff --git a/packages/lambda/src/models/nonprofitDonationTier.js b/packages/lambda/src/dynamo-models/nonprofitDonationTier.js similarity index 100% rename from packages/lambda/src/models/nonprofitDonationTier.js rename to packages/lambda/src/dynamo-models/nonprofitDonationTier.js diff --git a/packages/lambda/src/models/nonprofitSlide.js b/packages/lambda/src/dynamo-models/nonprofitSlide.js similarity index 100% rename from packages/lambda/src/models/nonprofitSlide.js rename to packages/lambda/src/dynamo-models/nonprofitSlide.js diff --git a/packages/lambda/src/models/paymentTransaction.js b/packages/lambda/src/dynamo-models/paymentTransaction.js similarity index 100% rename from packages/lambda/src/models/paymentTransaction.js rename to packages/lambda/src/dynamo-models/paymentTransaction.js diff --git a/packages/lambda/src/models/report.js b/packages/lambda/src/dynamo-models/report.js similarity index 100% rename from packages/lambda/src/models/report.js rename to packages/lambda/src/dynamo-models/report.js diff --git a/packages/lambda/src/models/sponsor.js b/packages/lambda/src/dynamo-models/sponsor.js similarity index 100% rename from packages/lambda/src/models/sponsor.js rename to packages/lambda/src/dynamo-models/sponsor.js diff --git a/packages/lambda/src/models/sponsorTier.js b/packages/lambda/src/dynamo-models/sponsorTier.js similarity index 100% rename from packages/lambda/src/models/sponsorTier.js rename to packages/lambda/src/dynamo-models/sponsorTier.js diff --git a/packages/lambda/src/models/user.js b/packages/lambda/src/dynamo-models/user.js similarity index 100% rename from packages/lambda/src/models/user.js rename to packages/lambda/src/dynamo-models/user.js diff --git a/packages/lambda/src/helpers/generator.js b/packages/lambda/src/helpers/generator.js index 818d076d..a960ea67 100644 --- a/packages/lambda/src/helpers/generator.js +++ b/packages/lambda/src/helpers/generator.js @@ -384,7 +384,7 @@ Generator.prototype.data = function (type, data) { */ Generator.prototype.model = function (type, data) { this._validateType(type); - const Model = require(`./../models/${type}`); + const Model = require(`./../dynamo-models/${type}`); return new Model(this.data(type, data)); }; diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js new file mode 100644 index 00000000..eb039cfd --- /dev/null +++ b/packages/lambda/src/models/connect.js @@ -0,0 +1,43 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const CloudFormation = require('./../aws/cloudformation'); +const SecretsManager = require('./../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); + +console.log("IN CONNECT"); +function init() { + console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); + + return new Sequelize({ + host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } + }); +} + +const sequelize = new Sequelize({ + host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } +}); + +module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js new file mode 100644 index 00000000..73bebb89 --- /dev/null +++ b/packages/lambda/src/models/index.js @@ -0,0 +1,46 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const db = {}; +const mysql2 = require('mysql2'); +const setting = require('./setting'); + +const sequelize = new Sequelize({ + host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', + username: 'readonly', + password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', + database: 'givesource', + port: 3306, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } +}); + +const models = [setting]; + +models.forEach(function (object) { + const model = require('./setting')(sequelize, Sequelize.DataTypes); + console.log('index model!'); /*DM: Debug */ + console.log(model); /*DM: Debug */ + db['Setting'] = model; +}); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); +console.log('db equals: ', db); /*DM: Debug */ + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +console.log(db); /*DM: Debug */ + +module.exports = db; diff --git a/packages/lambda/src/models/setting.js b/packages/lambda/src/models/setting.js new file mode 100644 index 00000000..4181d3ae --- /dev/null +++ b/packages/lambda/src/models/setting.js @@ -0,0 +1,10 @@ +'use strict'; + +const { sequelize, Sequelize } = require('./connect'); + +const Setting = sequelize.define('Setting', { + key: Sequelize.DataTypes.STRING, + value: Sequelize.DataTypes.STRING +}); + +console.log(Setting === sequelize.models.Setting); diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index 29161f4b..0493109f 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../models/content'); +const Content = require('./../dynamo-models/content'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/donations.js b/packages/lambda/src/repositories/donations.js index 5baf8ab2..09df6aa8 100644 --- a/packages/lambda/src/repositories/donations.js +++ b/packages/lambda/src/repositories/donations.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../models/donation'); +const Donation = require('./../dynamo-models/donation'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/donors.js b/packages/lambda/src/repositories/donors.js index eecc2162..cfb72a34 100644 --- a/packages/lambda/src/repositories/donors.js +++ b/packages/lambda/src/repositories/donors.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donor = require('./../models/donor'); +const Donor = require('./../dynamo-models/donor'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); diff --git a/packages/lambda/src/repositories/files.js b/packages/lambda/src/repositories/files.js index 743f2d42..72eff845 100644 --- a/packages/lambda/src/repositories/files.js +++ b/packages/lambda/src/repositories/files.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../models/file'); +const File = require('./../dynamo-models/file'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/messages.js b/packages/lambda/src/repositories/messages.js index 9ef994aa..b2ec7353 100644 --- a/packages/lambda/src/repositories/messages.js +++ b/packages/lambda/src/repositories/messages.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Message = require('./../models/message'); +const Message = require('./../dynamo-models/message'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/metrics.js b/packages/lambda/src/repositories/metrics.js index 442e2517..1429a66f 100644 --- a/packages/lambda/src/repositories/metrics.js +++ b/packages/lambda/src/repositories/metrics.js @@ -16,7 +16,7 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); -const Metric = require('./../models/metric'); +const Metric = require('./../dynamo-models/metric'); /** * MetricsRepository constructor diff --git a/packages/lambda/src/repositories/nonprofitDonationTiers.js b/packages/lambda/src/repositories/nonprofitDonationTiers.js index 8356ec59..0db38a25 100644 --- a/packages/lambda/src/repositories/nonprofitDonationTiers.js +++ b/packages/lambda/src/repositories/nonprofitDonationTiers.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const NonprofitDonationTier = require('../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('../dynamo-models/nonprofitDonationTier'); const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); diff --git a/packages/lambda/src/repositories/nonprofitDonations.js b/packages/lambda/src/repositories/nonprofitDonations.js index bbdb74fd..83aced1f 100644 --- a/packages/lambda/src/repositories/nonprofitDonations.js +++ b/packages/lambda/src/repositories/nonprofitDonations.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../models/donation'); +const Donation = require('./../dynamo-models/donation'); const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); diff --git a/packages/lambda/src/repositories/nonprofitReports.js b/packages/lambda/src/repositories/nonprofitReports.js index 1ec9383a..e2c38262 100644 --- a/packages/lambda/src/repositories/nonprofitReports.js +++ b/packages/lambda/src/repositories/nonprofitReports.js @@ -16,7 +16,7 @@ const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); -const Report = require('./../models/report'); +const Report = require('./../dynamo-models/report'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/nonprofitSlides.js b/packages/lambda/src/repositories/nonprofitSlides.js index 7e5844bc..41a410c2 100644 --- a/packages/lambda/src/repositories/nonprofitSlides.js +++ b/packages/lambda/src/repositories/nonprofitSlides.js @@ -15,7 +15,7 @@ */ const NonprofitRepository = require('./nonprofits'); -const NonprofitSlide = require('../models/nonprofitSlide'); +const NonprofitSlide = require('../dynamo-models/nonprofitSlide'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); diff --git a/packages/lambda/src/repositories/nonprofitUsers.js b/packages/lambda/src/repositories/nonprofitUsers.js index 6a0c50a7..649c602e 100644 --- a/packages/lambda/src/repositories/nonprofitUsers.js +++ b/packages/lambda/src/repositories/nonprofitUsers.js @@ -19,7 +19,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const User = require('./../models/user'); +const User = require('./../dynamo-models/user'); /** * NonprofitUsersRepository constructor diff --git a/packages/lambda/src/repositories/nonprofits.js b/packages/lambda/src/repositories/nonprofits.js index f470bb3b..af307afc 100644 --- a/packages/lambda/src/repositories/nonprofits.js +++ b/packages/lambda/src/repositories/nonprofits.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Nonprofit = require('./../models/nonprofit'); +const Nonprofit = require('./../dynamo-models/nonprofit'); const NonprofitHelper = require('./../helpers/nonprofit'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./../repositories/repository'); diff --git a/packages/lambda/src/repositories/paymentTransactions.js b/packages/lambda/src/repositories/paymentTransactions.js index 5178138d..ff49b1aa 100644 --- a/packages/lambda/src/repositories/paymentTransactions.js +++ b/packages/lambda/src/repositories/paymentTransactions.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const PaymentTransaction = require('./../models/paymentTransaction'); +const PaymentTransaction = require('./../dynamo-models/paymentTransaction'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/reports.js b/packages/lambda/src/repositories/reports.js index 498aff48..e90c2b9e 100644 --- a/packages/lambda/src/repositories/reports.js +++ b/packages/lambda/src/repositories/reports.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Report = require('./../models/report'); +const Report = require('./../dynamo-models/report'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index fff0c81d..4fe06c08 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -16,7 +16,7 @@ const _ = require('lodash'); const AWS = require('aws-sdk'); -const Model = require('./../models/model'); +const Model = require('./../dynamo-models/model'); const QueryBuilder = require('./../aws/queryBuilder'); /** diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 6b012a00..f3de6a0b 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -17,7 +17,7 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Setting = require('./../sql-models/setting'); +const Setting = require('../models/index').Setting; /** * SettingsRepository constructor @@ -46,17 +46,8 @@ SettingsRepository.prototype = new Repository(); * @return {Promise} */ SettingsRepository.prototype.get = function (key) { - const repository = this; - return new Promise(function (resolve, reject) { - repository.getByKey('key', key).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new Setting(data.Item)); - } - reject(new ResourceNotFoundException('The specified setting does not exist.')); - }).catch(function (err) { - reject(err); - }); - }); + console.log('key is: ', key); /*DM: Debug */ + return Setting.findOne({ where: {key: key}}); }; /** @@ -65,20 +56,8 @@ SettingsRepository.prototype.get = function (key) { * @return {Promise} */ SettingsRepository.prototype.getAll = function () { - const repository = this; - return new Promise(function (resolve, reject) { - repository.batchScan().then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Setting(item)); - }); - } - resolve(results); - }).catch(function (err) { - reject(err); - }); - }); + console.log(Setting); /*DM: Debug */ + return Setting.findAll(); }; /** diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index ef6a1d8c..8931e79d 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -18,7 +18,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const SponsorTier = require('./../models/sponsorTier'); +const SponsorTier = require('./../dynamo-models/sponsorTier'); /** * SponsorTiersRepository constructor diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 3739e01c..697f5b56 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -18,7 +18,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Sponsor = require('./../models/sponsor'); +const Sponsor = require('./../dynamo-models/sponsor'); const SponsorTiersRepository = require('./sponsorTiers'); /** diff --git a/packages/lambda/src/repositories/users.js b/packages/lambda/src/repositories/users.js index 2beaaa05..26055a8e 100644 --- a/packages/lambda/src/repositories/users.js +++ b/packages/lambda/src/repositories/users.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const User = require('./../models/user'); +const User = require('./../dynamo-models/user'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/sql-models/connect.js b/packages/lambda/src/sql-models/connect.js deleted file mode 100644 index 67c922dc..00000000 --- a/packages/lambda/src/sql-models/connect.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const CloudFormation = require('./../aws/cloudformation'); -const SecretsManager = require('./../aws/secretsManager'); -const mysql2 = require('mysql2'); -const Sequelize = require('sequelize'); - -console.log("IN CONNECT"); -function init() { - console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); - - const cloudFormation = new CloudFormation(); - cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { - const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadonlySecret').OutputValue; - const secretsManager = new SecretsManager(); - return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); - }).then(function (secret) { - console.log("SECRET IS " + secret); - console.log(secret); - const readonlySecret = JSON.parse(secret.SecretString); - return new Sequelize({ - host: readonlySecret.host, - username: readonlySecret.username, - password: readonlySecret.password, - database: readonlySecret.database, - port: readonlySecret.port, - //host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - //username: 'readonly', - //password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', - //database: 'givesource', - //port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } - }); - }); -} -//const sequelize = init(); -//module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; - -const sequelize = new Sequelize({ - host: 'joe-test-auroradbstack-z5gweu0i7813-rdscluster-odnvjq2syzbe.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'MXq5Ie9Rndsv5nc5cKIFlovt0GVm1k1G', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } -}); -module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; diff --git a/packages/lambda/src/sql-models/setting.js b/packages/lambda/src/sql-models/setting.js deleted file mode 100644 index 1a945884..00000000 --- a/packages/lambda/src/sql-models/setting.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -const { sequelize, Sequelize } = require('./connect') -//console.log("IN SETTINGS, SEQUELIZE IS "); -//console.log(sequelize); - -const Setting = sequelize.define('Setting', { - key: Sequelize.DataTypes.STRING, - value: Sequelize.DataTypes.STRING -}); - -module.exports = Setting; diff --git a/packages/lambda/test/models/donation.js b/packages/lambda/test/models/donation.js index 55c72e87..6e5bc697 100644 --- a/packages/lambda/test/models/donation.js +++ b/packages/lambda/test/models/donation.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Donation = require('../../src/models/donation'); -const Model = require('../../src/models/model'); +const Donation = require('../../src/dynamo-models/donation'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Donation', function () { diff --git a/packages/lambda/test/models/donor.js b/packages/lambda/test/models/donor.js index 80c19a8c..991f3ec4 100644 --- a/packages/lambda/test/models/donor.js +++ b/packages/lambda/test/models/donor.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Donor = require('../../src/models/donor'); -const Model = require('../../src/models/model'); +const Donor = require('../../src/dynamo-models/donor'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Donor', function () { diff --git a/packages/lambda/test/models/file.js b/packages/lambda/test/models/file.js index 6f5680f3..790b3b72 100644 --- a/packages/lambda/test/models/file.js +++ b/packages/lambda/test/models/file.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const File = require('../../src/models/file'); -const Model = require('../../src/models/model'); +const File = require('../../src/dynamo-models/file'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('File', function () { diff --git a/packages/lambda/test/models/message.js b/packages/lambda/test/models/message.js index 1fc653d7..3421b558 100644 --- a/packages/lambda/test/models/message.js +++ b/packages/lambda/test/models/message.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Message = require('../../src/models/message'); -const Model = require('../../src/models/model'); +const Message = require('../../src/dynamo-models/message'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Message', function () { diff --git a/packages/lambda/test/models/metric.js b/packages/lambda/test/models/metric.js index e82fa59c..90e9058e 100644 --- a/packages/lambda/test/models/metric.js +++ b/packages/lambda/test/models/metric.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Metric = require('../../src/models/metric'); -const Model = require('../../src/models/model'); +const Metric = require('../../src/dynamo-models/metric'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Metric', function () { diff --git a/packages/lambda/test/models/model.js b/packages/lambda/test/models/model.js index a1a2a568..41dc51bb 100644 --- a/packages/lambda/test/models/model.js +++ b/packages/lambda/test/models/model.js @@ -15,7 +15,7 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Model', function () { diff --git a/packages/lambda/test/models/nonprofit.js b/packages/lambda/test/models/nonprofit.js index aef7dcde..3c1fd296 100644 --- a/packages/lambda/test/models/nonprofit.js +++ b/packages/lambda/test/models/nonprofit.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Nonprofit = require('../../src/models/nonprofit'); +const Model = require('../../src/dynamo-models/model'); +const Nonprofit = require('../../src/dynamo-models/nonprofit'); const NonprofitHelper = require('../../src/helpers/nonprofit'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/nonprofitSlide.js b/packages/lambda/test/models/nonprofitSlide.js index e2e3a625..eb7c3e38 100644 --- a/packages/lambda/test/models/nonprofitSlide.js +++ b/packages/lambda/test/models/nonprofitSlide.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const NonprofitSlide = require('../../src/models/nonprofitSlide'); +const Model = require('../../src/dynamo-models/model'); +const NonprofitSlide = require('../../src/dynamo-models/nonprofitSlide'); const NonprofitSlideHelper = require('../../src/helpers/nonprofitSlide'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/paymentTransaction.js b/packages/lambda/test/models/paymentTransaction.js index a4ec101c..d9e0f90e 100644 --- a/packages/lambda/test/models/paymentTransaction.js +++ b/packages/lambda/test/models/paymentTransaction.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const PaymentTransaction = require('../../src/models/paymentTransaction'); -const Model = require('../../src/models/model'); +const PaymentTransaction = require('../../src/dynamo-models/paymentTransaction'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('PaymentTransaction', function () { diff --git a/packages/lambda/test/models/report.js b/packages/lambda/test/models/report.js index caf11755..e05de769 100644 --- a/packages/lambda/test/models/report.js +++ b/packages/lambda/test/models/report.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Report = require('../../src/models/report'); +const Model = require('../../src/dynamo-models/model'); +const Report = require('../../src/dynamo-models/report'); const ReportHelper = require('../../src/helpers/report'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/setting.js b/packages/lambda/test/models/setting.js index 9519fc56..7ceca542 100644 --- a/packages/lambda/test/models/setting.js +++ b/packages/lambda/test/models/setting.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Setting = require('../../src/models/setting'); +const Model = require('../../src/dynamo-models/model'); +const Setting = require('../../src/dynamo-models/setting'); const TestHelper = require('../helpers/test'); describe('Setting', function () { diff --git a/packages/lambda/test/models/sponsor.js b/packages/lambda/test/models/sponsor.js index 9f761f43..2a1a4fb0 100644 --- a/packages/lambda/test/models/sponsor.js +++ b/packages/lambda/test/models/sponsor.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Sponsor = require('../../src/models/sponsor'); +const Model = require('../../src/dynamo-models/model'); +const Sponsor = require('../../src/dynamo-models/sponsor'); const TestHelper = require('../helpers/test'); describe('Sponsor', function () { diff --git a/packages/lambda/test/models/sponsorTier.js b/packages/lambda/test/models/sponsorTier.js index bc1d8fb1..148e64eb 100644 --- a/packages/lambda/test/models/sponsorTier.js +++ b/packages/lambda/test/models/sponsorTier.js @@ -15,9 +15,9 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); +const Model = require('../../src/dynamo-models/model'); const SponsorHelper = require('../../src/helpers/sponsor'); -const SponsorTier = require('../../src/models/sponsorTier'); +const SponsorTier = require('../../src/dynamo-models/sponsorTier'); const TestHelper = require('../helpers/test'); describe('SponsorTier', function () { diff --git a/packages/lambda/test/models/user.js b/packages/lambda/test/models/user.js index cd969a15..c7364283 100644 --- a/packages/lambda/test/models/user.js +++ b/packages/lambda/test/models/user.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const User = require('../../src/models/user'); +const Model = require('../../src/dynamo-models/model'); +const User = require('../../src/dynamo-models/user'); const TestHelper = require('../helpers/test'); describe('User', function () { diff --git a/packages/lambda/test/repositories/donations.js b/packages/lambda/test/repositories/donations.js index f64c9134..5a8c3301 100644 --- a/packages/lambda/test/repositories/donations.js +++ b/packages/lambda/test/repositories/donations.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Donation = require('../../src/models/donation'); +const Donation = require('../../src/dynamo-models/donation'); const DonationsRepository = require('../../src/repositories/donations'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/donors.js b/packages/lambda/test/repositories/donors.js index dcd7219c..67f25d62 100644 --- a/packages/lambda/test/repositories/donors.js +++ b/packages/lambda/test/repositories/donors.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Donor = require('../../src/models/donor'); +const Donor = require('../../src/dynamo-models/donor'); const DonorsRepository = require('../../src/repositories/donors'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/messages.js b/packages/lambda/test/repositories/messages.js index bac7f7fb..40f15b68 100644 --- a/packages/lambda/test/repositories/messages.js +++ b/packages/lambda/test/repositories/messages.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Message = require('../../src/models/message'); +const Message = require('../../src/dynamo-models/message'); const MessagesRepository = require('../../src/repositories/messages'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/metrics.js b/packages/lambda/test/repositories/metrics.js index dac1ce33..5b00a07a 100644 --- a/packages/lambda/test/repositories/metrics.js +++ b/packages/lambda/test/repositories/metrics.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Metric = require('./../../src/models/metric'); +const Metric = require('./../../src/dynamo-models/metric'); const MetricsRepository = require('./../../src/repositories/metrics'); const promiseMe = require('mocha-promise-me'); const Repository = require('./../../src/repositories/repository'); diff --git a/packages/lambda/test/repositories/nonprofitSlides.js b/packages/lambda/test/repositories/nonprofitSlides.js index 2aec7125..e5a0a2f5 100644 --- a/packages/lambda/test/repositories/nonprofitSlides.js +++ b/packages/lambda/test/repositories/nonprofitSlides.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Slide = require('../../src/models/nonprofitSlide'); +const Slide = require('../../src/dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('../../src/repositories/nonprofitSlides'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/nonprofits.js b/packages/lambda/test/repositories/nonprofits.js index 03acbc4a..318dfe84 100644 --- a/packages/lambda/test/repositories/nonprofits.js +++ b/packages/lambda/test/repositories/nonprofits.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Nonprofit = require('../../src/models/nonprofit'); +const Nonprofit = require('../../src/dynamo-models/nonprofit'); const NonprofitsRepository = require('../../src/repositories/nonprofits'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/paymentTransactions.js b/packages/lambda/test/repositories/paymentTransactions.js index a2c9ff91..4c8dd7f5 100644 --- a/packages/lambda/test/repositories/paymentTransactions.js +++ b/packages/lambda/test/repositories/paymentTransactions.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const PaymentTransaction = require('../../src/models/paymentTransaction'); +const PaymentTransaction = require('../../src/dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('../../src/repositories/paymentTransactions'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/reports.js b/packages/lambda/test/repositories/reports.js index 00017b7c..ce1dde64 100644 --- a/packages/lambda/test/repositories/reports.js +++ b/packages/lambda/test/repositories/reports.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Report = require('../../src/models/report'); +const Report = require('../../src/dynamo-models/report'); const ReportsRepository = require('../../src/repositories/reports'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/settings.js b/packages/lambda/test/repositories/settings.js index d0e8c0e0..179bfd10 100644 --- a/packages/lambda/test/repositories/settings.js +++ b/packages/lambda/test/repositories/settings.js @@ -18,7 +18,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const promiseMe = require('mocha-promise-me'); const Repository = require('./../../src/repositories/repository'); -const Setting = require('./../../src/models/setting'); +const Setting = require('./../../src/dynamo-models/setting'); const SettingsRepository = require('./../../src/repositories/settings'); const TestHelper = require('./../helpers/test'); diff --git a/packages/lambda/test/repositories/sponsorTiers.js b/packages/lambda/test/repositories/sponsorTiers.js index 26876d83..795a957d 100644 --- a/packages/lambda/test/repositories/sponsorTiers.js +++ b/packages/lambda/test/repositories/sponsorTiers.js @@ -17,7 +17,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const Repository = require('../../src/repositories/repository'); -const SponsorTier = require('../../src/models/sponsorTier'); +const SponsorTier = require('../../src/dynamo-models/sponsorTier'); const SponsorTiersRepository = require('../../src/repositories/sponsorTiers'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/sponsors.js b/packages/lambda/test/repositories/sponsors.js index f907e50d..4aa9f34f 100644 --- a/packages/lambda/test/repositories/sponsors.js +++ b/packages/lambda/test/repositories/sponsors.js @@ -17,7 +17,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const Repository = require('../../src/repositories/repository'); -const Sponsor = require('../../src/models/sponsor'); +const Sponsor = require('../../src/dynamo-models/sponsor'); const SponsorsRepository = require('../../src/repositories/sponsors'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/users.js b/packages/lambda/test/repositories/users.js index 6fedaa33..e1a6a32d 100644 --- a/packages/lambda/test/repositories/users.js +++ b/packages/lambda/test/repositories/users.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const User = require('../../src/models/user'); +const User = require('../../src/dynamo-models/user'); const UsersRepository = require('../../src/repositories/users'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); From 6eb2c6531cc29ae166247aa750485ffb7f3e8416 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 13 Aug 2020 14:16:28 -0500 Subject: [PATCH 039/140] [GD-1639]: Research/Do: Implement mysql node library for schema migrations * Added credentials for non-admin users * Added lambdas and invokers to bootstrap and run initial migration * Added code to release migrations when lambda functions are released * Added initial migration with test table creations. * Added sequelize for ORM * Added umzug for running migrations * Added s3 function to download the migration files onto the lambda container * Added lambda to bootstrap database and non-admin users with their passwords * Added lambda to run schema migration --- .../templates/givesource-aurora.yml | 313 ++++++--- .../cloudformation/templates/givesource.yml | 3 +- packages/lambda/.gitignore | 2 +- packages/lambda/bin/release.js | 24 +- packages/lambda/config/webpack.config.js | 5 +- packages/lambda/migrations/00_initial.js | 75 +++ packages/lambda/package-lock.json | 596 ++++++++++++++---- packages/lambda/package.json | 6 +- packages/lambda/src/aws/s3.js | 35 +- .../src/database/bootstrapDatabase/index.js | 83 +++ .../lambda/src/database/createSchema/index.js | 318 ---------- .../src/database/migrateDatabase/index.js | 95 +++ 12 files changed, 1020 insertions(+), 535 deletions(-) create mode 100644 packages/lambda/migrations/00_initial.js create mode 100644 packages/lambda/src/database/bootstrapDatabase/index.js delete mode 100644 packages/lambda/src/database/createSchema/index.js create mode 100644 packages/lambda/src/database/migrateDatabase/index.js diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index e6fde2db..7820ed3e 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -2,43 +2,47 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS Aurora resources for Givesource(R) Parameters: - DBMasterUserName: + DatabaseAdminUser: AllowedPattern: "[a-zA-Z0-9_]+" ConstraintDescription: must be between 1 to 16 alphanumeric characters. Description: The database admin account user name, between 1 to 16 alphanumeric characters. MaxLength: '16' MinLength: '1' Type: String - Default: adminUser + Default: admin + DatabaseMaintenanceUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database maintenance account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: maintenance + DatabaseReadwriteUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readwrite account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readwrite + DatabaseReadonlyUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readonly account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readonly + DatabaseName: + Type: String + Default: givesource StackName: Type: String LambdaSecurityGroupId: Type: String Resources: - SecretsManagerManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - secretsmanager:GetSecretValue - Resource: !Ref DBSecret - CreateSchemaLambdaRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Action: sts:AssumeRole - Principal: - Service: - - lambda.amazonaws.com - ManagedPolicyArns: - - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - - !Ref SecretsManagerManagedPolicy - GivesourceAuroraSecurityGroup: + DBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Ingress/egress rules for aurora @@ -48,15 +52,6 @@ Resources: Tags: - Key: Name Value: givesource-aurora - LambdaAuroraIngress: - Type: AWS::EC2::SecurityGroupIngress - Properties: - Description: allows access from lambda into aurora - GroupId: !GetAtt GivesourceAuroraSecurityGroup.GroupId - IpProtocol: tcp - FromPort: 3306 - ToPort: 3306 - SourceSecurityGroupId: !Ref LambdaSecurityGroupId DBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: @@ -64,22 +59,76 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DBSecret: + AdminUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-AdminUserSecret + Description: Givesource database auto-generated admin user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + AdminUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref AdminUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + MaintenanceUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-MaintenanceUserSecret + Description: Givesource database auto-generated maintenance user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + MaintenanceUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref MaintenanceUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + ReadwriteUserSecret: Type: AWS::SecretsManager::Secret Properties: - Name: !Sub "${AWS::StackName}-AuroraUserSecret" - Description: RDS database auto-generated user password + Name: !Sub ${AWS::StackName}-ReadwriteUserSecret + Description: Givesource database auto-generated readwrite user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}' - GenerateStringKey: "password" - PasswordLength: 30 + SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}"}' + GenerateStringKey: password + PasswordLength: 32 ExcludeCharacters: '"@/\' + ReadwriteUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadwriteUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + ReadonlyUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${AWS::StackName}-ReadonlyUserSecret + Description: Givesource database auto-generated readonly user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + ReadonlyUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadonlyUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster RDSCluster: Type: AWS::RDS::DBCluster Properties: {{=<% %>=}} - MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}' - MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}' + MasterUsername: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:username}}' + MasterUserPassword: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:password}}' <%={{ }}=%> Engine: aurora-mysql EngineMode: serverless @@ -89,32 +138,69 @@ Resources: AutoPause: true MaxCapacity: 16 MinCapacity: 1 - SecondsUntilAutoPause: 900 # 15 min + SecondsUntilAutoPause: 900 DBSubnetGroupName: !Ref DBSubnetGroup VpcSecurityGroupIds: - - !GetAtt GivesourceAuroraSecurityGroup.GroupId - DependsOn: DBSecret - CreateSchemaLambdaFunction: + - !GetAtt DBSecurityGroup.GroupId + DependsOn: AdminUserSecret + LambdaAuroraIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: allows access from lambda into aurora + GroupId: !GetAtt DBSecurityGroup.GroupId + IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupId: !Ref LambdaSecurityGroupId + BootstrapDatabaseLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref AdminUserSecret + - !Ref MaintenanceUserSecret + - !Ref ReadwriteUserSecret + - !Ref ReadonlyUserSecret + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + BootstrapDatabaseLambdaFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} - S3Key: fn/{{version}}/CreateSchema.zip + S3Key: fn/{{version}}/BootstrapDatabase.zip Description: Database Init Environment: Variables: AWS_STACK_NAME: !Ref AWS::StackName - DATABASE_USER: !Ref DBMasterUserName - DATABASE_SECRET_ARN: !Ref DBSecret - AURORA_DB_HOST: !GetAtt RDSCluster.Endpoint.Address - SECRETS_MANAGER_SECRET_ID: !Sub "${AWS::StackName}-AuroraUserSecret" - FunctionName: !Sub ${StackName}-CreateSchema - Handler: "index.handle" - MemorySize: 128 - Role: !GetAtt CreateSchemaLambdaRole.Arn - Runtime: "nodejs12.x" - Timeout: 120 #seconds + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + ADMIN_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-AdminUserSecret + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret + READWRITE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadwriteUserSecret + READONLY_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadonlyUserSecret + DATABASE_NAME: !Ref DatabaseName + FunctionName: !Sub ${StackName}-BootstrapDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt BootstrapDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 60 VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroupId @@ -122,10 +208,77 @@ Resources: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet DependsOn: RDSCluster - CreateSchemaLambdaCustomResource: - Type: "Custom::CreateSchemaLambdaInvoker" + BootstrapDatabaseLambdaLambdaInvoker: + Type: Custom::BootstrapDatabaseLambdaInvoker + Properties: + ServiceToken: !GetAtt BootstrapDatabaseLambdaFunction.Arn + MigrateDatabaseLambdaRole: + Type: AWS::IAM::Role Properties: - ServiceToken: !GetAtt CreateSchemaLambdaFunction.Arn + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref MaintenanceUserSecret + - Effect: Allow + Action: + - s3:ListBucket + Resource: + - arn:aws:s3:::{{awsReleaseBucket}} + - Effect: Allow + Action: + - s3:GetObject* + Resource: + - arn:aws:s3:::{{awsReleaseBucket}}/* + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + MigrateDatabaseLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/MigrateDatabase.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref AWS::StackName + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret + DATABASE_NAME: !Ref DatabaseName + MIGRATIONS_BUCKET: {{awsReleaseBucket}} + MIGRATIONS_LOCATION: migrations/{{version}} + FunctionName: !Sub ${StackName}-MigrateDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt MigrateDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 180 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + DependsOn: RDSCluster + MigrateDatabaseLambdaLambdaInvoker: + Type: Custom::MigrateDatabaseLambdaInvoker + Properties: + ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn + DependsOn: BootstrapDatabaseLambdaLambdaInvoker Outputs: StackName: Description: Aurora Stack Name @@ -133,11 +286,17 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-StackName - DBSecretArn: - Description: DBSecret Arn - Value: !Ref DBSecret + ReadwriteUserSecretId: + Description: Secret Id for the readwrite user + Value: !Sub ${AWS::StackName}-ReadwriteUserSecret + Export: + Name: !Sub ${AWS::StackName}-ReadwriteUserSecretId + + ReadonlyUserSecretId: + Description: Secret Id for the readonly user + Value: !Sub ${AWS::StackName}-ReadonlyUserSecret Export: - Name: !Sub ${AWS::StackName}-DBSecretArn + Name: !Sub ${AWS::StackName}-UserSecretId DatabaseClusterArn: Description: Aurora Cluster ARN @@ -145,26 +304,8 @@ Outputs: Export: Name: !Sub ${AWS::StackName}-DatabaseClusterArn - DatabaseSecretArn: - Description: Aurora Secret ARN - Value: !Ref DBSecret - Export: - Name: !Sub ${AWS::StackName}-DatabaseSecretArn - - DatabaseClusterID: - Description: Aurora Cluster ID - Value: !Ref RDSCluster - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterID - - AuroraDbURL: - Description: Aurora Database URL + DatabaseEndpoint: + Description: Aurora Database Endpoint Value: !GetAtt RDSCluster.Endpoint.Address Export: - Name: !Sub ${AWS::StackName}-DatabaseURL - - DatabaseMasterUserName: - Description: Aurora Database User - Value: !Ref DBMasterUserName - Export: - Name: !Sub ${AWS::StackName}-DatabaseMasterUserName + Name: !Sub ${AWS::StackName}-DatabaseEndpoint diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 2308f345..50cc7f04 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -109,6 +109,7 @@ Resources: LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 + DependsOn: LambdaSecurityGroup S3Stack: Type: AWS::CloudFormation::Stack @@ -795,4 +796,4 @@ Outputs: Value: !GetAtt CustomStack.Outputs.CognitoUserPoolId Version: - Value: {{version}} \ No newline at end of file + Value: {{version}} diff --git a/packages/lambda/.gitignore b/packages/lambda/.gitignore index 7d42b7ed..39638e4e 100644 --- a/packages/lambda/.gitignore +++ b/packages/lambda/.gitignore @@ -13,4 +13,4 @@ dist/ clean # Ignore build directory -build/ \ No newline at end of file +build/ diff --git a/packages/lambda/bin/release.js b/packages/lambda/bin/release.js index b0e22b2c..b01a96b6 100755 --- a/packages/lambda/bin/release.js +++ b/packages/lambda/bin/release.js @@ -59,6 +59,19 @@ const release = function (region) { }); }; +const releaseMigrations = function () { + const s3 = new S3(); + const migrationsDir = path.resolve(__dirname, './../migrations'); + const migrations = fs.readdirSync(migrationsDir); + const bucketName = config.get('release.AWS_RELEASE_BUCKET'); + const bucketRegion = config.get('release.AWS_RELEASE_BUCKET_REGION'); + migrations.forEach(function (migrationName) { + const objectName = 'migrations/' + packageJson.version + '/' + migrationName; + const body = fs.readFileSync(migrationsDir + '/' + migrationName); + return s3.putObject(bucketRegion, bucketName, objectName, body); + }); +}; + let promise = Promise.resolve(); if (process.argv[2] !== '--force' && process.argv[2] !== '-F') { config.get('release.AWS_LAMBDA_RELEASE_BUCKET_AVAILABLE_REGIONS').forEach(function (region) { @@ -80,4 +93,13 @@ promise.then(function () { console.log('Lambda functions released'); }).catch(function (err) { console.log(err); -}); \ No newline at end of file +}); + +promise.then(function () { + return releaseMigrations(); +}).then(function () { + console.log('Database migrations released'); +}).catch(function (err) { + console.log(err); +}); + diff --git a/packages/lambda/config/webpack.config.js b/packages/lambda/config/webpack.config.js index 1707fc43..967a42bf 100644 --- a/packages/lambda/config/webpack.config.js +++ b/packages/lambda/config/webpack.config.js @@ -157,7 +157,8 @@ module.exports = { SendRegistrationPendingEmail: './src/custom/sendRegistrationPendingEmail/index.js', // Database Lambda Functions - CreateSchema: './src/database/createSchema/index.js', + BootstrapDatabase: './src/database/bootstrapDatabase/index.js', + MigrateDatabase: './src/database/migrateDatabase/index.js', }, output: { filename: '[name]/index.js', @@ -186,4 +187,4 @@ module.exports = { resolve: { modules: [path.resolve(__dirname, '../src'), 'node_modules'] } -}; \ No newline at end of file +}; diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js new file mode 100644 index 00000000..25594895 --- /dev/null +++ b/packages/lambda/migrations/00_initial.js @@ -0,0 +1,75 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Settings', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + key: { + type: Sequelize.STRING + }, + value: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + isDeleted: { + type: Sequelize.BOOLEAN, + defaultValue: false, + allowNull: false + } + }).then( + queryInterface.createTable('Contents', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + isDeleted: { + type: Sequelize.BOOLEAN, + defaultValue: false, + allowNull: false + }, + parentId: { + type: Sequelize.INTEGER + }, + sortOrder: { + type: Sequelize.INTEGER + }, + type: { + type: Sequelize.STRING + }, + value: { + type: Sequelize.STRING + }, + name: { + type: Sequelize.STRING + } + }) + ); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Settings').then( + queryInterface.dropTable('Contents') + );; + } +}; diff --git a/packages/lambda/package-lock.json b/packages/lambda/package-lock.json index ae5c36d5..a7e195a3 100644 --- a/packages/lambda/package-lock.json +++ b/packages/lambda/package-lock.json @@ -127,6 +127,11 @@ "to-fast-properties": "^2.0.0" } }, + "@types/node": { + "version": "14.0.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz", + "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==" + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -386,6 +391,16 @@ "color-convert": "^1.9.0" } }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -703,11 +718,6 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, - "bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" - }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -736,8 +746,7 @@ "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { "version": "4.11.8", @@ -902,6 +911,11 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -1013,6 +1027,15 @@ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1373,7 +1396,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cp-file": { "version": "6.2.0", @@ -1571,6 +1595,11 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -1618,6 +1647,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -1736,6 +1770,11 @@ "estraverse": "^4.1.1" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -2199,25 +2238,29 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -2227,13 +2270,15 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, "requires": { @@ -2243,37 +2288,43 @@ }, "chownr": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "3.2.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "optional": true, "requires": { @@ -2282,25 +2333,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, "requires": { @@ -2309,13 +2364,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -2331,7 +2388,8 @@ }, "glob": { "version": "7.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "optional": true, "requires": { @@ -2345,13 +2403,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -2360,7 +2420,8 @@ }, "ignore-walk": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "optional": true, "requires": { @@ -2369,7 +2430,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -2379,19 +2441,22 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, "requires": { @@ -2400,13 +2465,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, "requires": { @@ -2415,13 +2482,15 @@ }, "minimist": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true, "optional": true }, "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "optional": true, "requires": { @@ -2431,7 +2500,8 @@ }, "minizlib": { "version": "1.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "optional": true, "requires": { @@ -2440,7 +2510,8 @@ }, "mkdirp": { "version": "0.5.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", "dev": true, "optional": true, "requires": { @@ -2449,13 +2520,15 @@ }, "ms": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "optional": true }, "needle": { "version": "2.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", "dev": true, "optional": true, "requires": { @@ -2466,7 +2539,8 @@ }, "node-pre-gyp": { "version": "0.14.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "dev": true, "optional": true, "requires": { @@ -2484,7 +2558,8 @@ }, "nopt": { "version": "4.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "optional": true, "requires": { @@ -2494,7 +2569,8 @@ }, "npm-bundled": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "optional": true, "requires": { @@ -2503,13 +2579,15 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "dev": true, "optional": true, "requires": { @@ -2520,7 +2598,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -2532,19 +2611,22 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, "requires": { @@ -2553,19 +2635,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -2575,19 +2660,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -2599,7 +2687,8 @@ }, "readable-stream": { "version": "2.3.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "optional": true, "requires": { @@ -2614,7 +2703,8 @@ }, "rimraf": { "version": "2.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "optional": true, "requires": { @@ -2623,43 +2713,50 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, "requires": { @@ -2670,7 +2767,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -2679,7 +2777,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, "requires": { @@ -2688,13 +2787,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.13", - "bundled": true, + "resolved": false, + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "optional": true, "requires": { @@ -2709,13 +2810,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -2724,13 +2827,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "optional": true } @@ -2748,6 +2853,14 @@ "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg=", "dev": true }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -3053,6 +3166,11 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3382,6 +3500,11 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3795,8 +3918,7 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash.clonedeep": { "version": "4.5.0", @@ -3882,6 +4004,11 @@ "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -3901,7 +4028,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "requires": { "yallist": "^3.0.2" } @@ -4255,48 +4381,53 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "requires": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" + "mysql2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", + "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", + "requires": { + "cardinal": "^2.1.1", + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" }, "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "safer-buffer": ">= 2.1.2 < 3" } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "requires": { - "safe-buffer": "~5.1.0" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" } } }, @@ -4798,6 +4929,11 @@ } } }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", @@ -4961,6 +5097,76 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pg": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.0.tgz", + "integrity": "sha512-jQPKWHWxbI09s/Z9aUvoTbvGgoj98AU7FDCcQ7kdejupn/TcNpx56v2gaOTzXkzOajmOEJEdi9eTh9cA2RVAjQ==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.3.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.5", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + } + } + }, + "pg-connection-string": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" + }, + "pg-hstore": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", + "integrity": "sha512-qpeTpdkguFgfdoidtfeTho1Q1zPVPbtMHgs8eQ+Aan05iLmIs3Z3oo5DOZRclPGoQ4i68I1kCtQSJSa7i0ZVYg==", + "requires": { + "underscore": "^1.7.0" + } + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", + "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" + }, + "pg-protocol": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", + "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "^1.0.0" + } + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -4982,6 +5188,29 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz", + "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5009,8 +5238,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { "version": "1.1.31", @@ -5176,6 +5404,14 @@ "readable-stream": "^2.0.2" } }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5313,6 +5549,14 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, "rimraf": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", @@ -5382,8 +5626,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "samsam": { "version": "1.1.2", @@ -5423,6 +5666,74 @@ "upper-case-first": "^1.1.2" } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.3.tgz", + "integrity": "sha512-WO/b1ehjSFKlBCHzwZoaPhoW3WyXXy9x74yPrOP8NpE67wzbv0dIucDO4a+THLVyl3lnv3nFMZdJRdkUgb/ZAw==", + "requires": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", + "toposort-class": "^1.0.1", + "uuid": "^8.1.0", + "validator": "^10.11.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "uuid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" + } + } + }, + "sequelize-pool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -5755,6 +6066,14 @@ "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6101,8 +6420,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", @@ -6228,6 +6546,11 @@ "repeat-string": "^1.6.1" } }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -6316,6 +6639,19 @@ } } }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "requires": { + "bluebird": "^3.7.2" + } + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + }, "unicode": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/unicode/-/unicode-11.0.1.tgz", @@ -6471,7 +6807,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "uuid-validate": { "version": "0.0.2", @@ -6500,6 +6837,11 @@ "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.10.0.tgz", "integrity": "sha1-DZcBTX4Zy+ikeAx5L2C1BaQwev0=" }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -6636,6 +6978,14 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6707,8 +7057,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "4.0.0", @@ -6719,8 +7068,7 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" }, "yargs": { "version": "12.0.5", diff --git a/packages/lambda/package.json b/packages/lambda/package.json index 3bc06253..42bf4e59 100644 --- a/packages/lambda/package.json +++ b/packages/lambda/package.json @@ -23,8 +23,12 @@ "dotenv": "^4.0.0", "json-loader": "^0.5.7", "mime": "^2.2.2", - "mysql": "^2.18.1", + "mysql2": "^2.1.0", + "pg": "^8.3.0", + "pg-hstore": "^2.3.3", "rimraf": "^2.6.1", + "sequelize": "^6.3.3", + "umzug": "^2.3.0", "validate.js": "0.10.0" }, "devDependencies": { diff --git a/packages/lambda/src/aws/s3.js b/packages/lambda/src/aws/s3.js index b4da02cd..1a06a0b4 100644 --- a/packages/lambda/src/aws/s3.js +++ b/packages/lambda/src/aws/s3.js @@ -16,6 +16,8 @@ const AWS = require('aws-sdk'); const mime = require('mime'); +const fs = require('fs'); +const path = require('path'); /** * S3 constructor @@ -49,6 +51,37 @@ S3.prototype.getObject = function (region, bucketName, objectName) { }); }; +/** + * Download an object from AWS S3 + * + * @param {string} region + * @param {string} bucketName + * @param {string} objectName + * @param {string} destPath + * @return {Promise} + */ +S3.prototype.downloadObject = function (region, bucketName, objectName, destPath) { + const awsS3 = new AWS.S3({region: region}); + return new Promise(function (resolve, reject) { + const params = { + Bucket: bucketName, + Key: objectName + }; + awsS3.getObject(params, function (err, result) { + if (err) { + reject(err); + } + + var filepath = path.join(destPath, objectName); + fs.mkdirSync(path.dirname(filepath), {recursive: true}); + if (result['ContentType'] != 'application/x-directory') { + fs.writeFileSync(filepath, result.Body.toString()); + } + resolve(result); + }); + }); +}; + /** * Put an object on AWS S3 * @@ -198,4 +231,4 @@ S3.prototype.getSignedUrl = function (region, bucketName, filePath, contentType, }); }; -module.exports = S3; \ No newline at end of file +module.exports = S3; diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js new file mode 100644 index 00000000..98e9eda9 --- /dev/null +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -0,0 +1,83 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const logger = require('./../../helpers/log'); +const response = require('cfn-response'); +const Request = require('./../../aws/request'); +const SecretsManager = require('./../../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); + +exports.handle = function (event, context, callback) { + logger.log('bootstrapDatabase event: %j', event); + + const request = new Request(event, context); + const secretsManager = new SecretsManager(); + + if (event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS); + return; + } + + request.validate().then(function () { + return Promise.all([ + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.ADMIN_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID), + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READONLY_DATABASE_SECRET_ID) + ]); + }).then(function (secrets) { + const dbHost = process.env.DATABASE_HOST; + const dbName = process.env.DATABASE_NAME; + const adminSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.ADMIN_DATABASE_SECRET_ID).SecretString); + const maintenanceSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.MAINTENANCE_DATABASE_SECRET_ID).SecretString); + const readwriteSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READWRITE_DATABASE_SECRET_ID).SecretString); + const readonlySecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READONLY_DATABASE_SECRET_ID).SecretString); + + const sequelize = new Sequelize({ + host: dbHost, + username: adminSecret.username, + password: adminSecret.password, + dialect: 'mysql', + dialectModule: mysql2, + port: 3306, + logging: false, // don't log the sql so we don't log the passwords + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS', + multipleStatements: true + } + }); + + // TODO: Add REQUIRE SSL to the grants + return sequelize.query( + 'CREATE DATABASE IF NOT EXISTS `' + dbName + '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; ' + + 'CREATE USER IF NOT EXISTS "' + maintenanceSecret.username + '"@"%" IDENTIFIED BY "' + maintenanceSecret.password + '"; ' + + 'GRANT ALL PRIVILEGES ON `' + dbName+ '`.* TO "' + maintenanceSecret.username + '"@"%"; ' + + 'CREATE USER IF NOT EXISTS "' + readwriteSecret.username + '"@"%" IDENTIFIED BY "' + readwriteSecret.password + '"; ' + + 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%"; ' + + 'CREATE USER IF NOT EXISTS "' + readonlySecret.username + '"@"%" IDENTIFIED BY "' + readonlySecret.password + '"; ' + + 'GRANT SELECT ON `' + dbName+ '`.* TO "' + readonlySecret.username + '"@"%";' + ); + }).then(function () { + response.send(event, context, response.SUCCESS); + callback(); + }).catch(function (err) { + logger.log(err); + response.send(event, context, response.FAILED); + callback(err); + }); +}; diff --git a/packages/lambda/src/database/createSchema/index.js b/packages/lambda/src/database/createSchema/index.js deleted file mode 100644 index dc24ea6d..00000000 --- a/packages/lambda/src/database/createSchema/index.js +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2019 Firespring, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const mysql = require("mysql"); -const response = require('cfn-response'); -const Request = require('./../../aws/request'); -const SecretsManager = require('./../../aws/secretsManager'); - -exports.handle = function (event, context, callback) { - console.log(JSON.stringify(event)); - const secretsManager = new SecretsManager(); - const request = new Request(event, context); - - if (event.RequestType === 'Update' || event.RequestType === 'Delete') { - response.send(event, context, response.SUCCESS, {}); - return; - } - - request.validate().then(function () { - return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.SECRETS_MANAGER_SECRET_ID) - }).then(function (res) { - if ('SecretString' in res) { - let connection = mysql.createConnection({ - host: process.env.AURORA_DB_HOST, - user: process.env.DATABASE_USER, - password: JSON.parse(res.SecretString).password, - ssl: true, - port: 3306 - }); - - connection.connect(function (err) { - if (err) throw err; - console.log('connected!'); /*DM: Debug */ - }); - - connection.query('CREATE DATABASE IF NOT EXISTS `givesource` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;', function (err, rows, fields) { - if (err) throw err; - }); - - connection.changeUser({database: 'givesource'}); - - //create the database - connection.query('DROP TABLE IF EXISTS contents'); - - connection.query( - 'CREATE TABLE `contents` (' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`parentId` INT(11) NOT NULL DEFAULT 0, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_contents_parent_id_index` (`parentId`))'); - - connection.query('DROP TABLE IF EXISTS donations'); - - connection.query('CREATE TABLE `donations` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - '`count` INT(11) NOT NULL DEFAULT 0, ' + - '`fees` INT(11) NOT NULL DEFAULT 0, ' + - '`isAnonymous` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isFeeCovered` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`isOfflineDonation` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - '`paymentTransactionIsTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`paymentTransactionId` INT(11) NOT NULL DEFAULT 0, ' + - '`subtotal` INT(11) NOT NULL DEFAULT 0, ' + - '`subtotalChargedToCard` INT(11) NOT NULL DEFAULT 0, ' + - '`total` INT(11) NOT NULL DEFAULT 0, ' + - '`type` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`donorId` INT(11) NOT NULL DEFAULT 0, ' + - '`note` VARCHAR(255) DEFAULT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_donations_nonprofit_id` (`nonprofitId`), ' + - 'KEY `ix_donations_payment_transaction_id` (`paymentTransactionId`), ' + - 'KEY `ix_donations_donor_id` (`donorId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS donors'); - - connection.query('CREATE TABLE `donors` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`amountForNonprofit` INT(11) NOT NULL DEFAULT 0, ' + - '`address1` VARCHAR(50) NOT NULL, ' + - '`address2` VARCHAR(50) NOT NULL, ' + - '`city` VARCHAR(50) NOT NULL, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`state` VARCHAR(50) NOT NULL, ' + - '`zip` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_donors_email` (`email`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS files'); - - connection.query('CREATE TABLE `files` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`path` VARCHAR(50) NOT NULL, ' + - '`filename` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS messages'); - - connection.query('CREATE TABLE `messages` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`message` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS metrics'); - - connection.query('CREATE TABLE `metrics` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`key` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofit_donation_tiers'); - - connection.query('CREATE TABLE `nonprofit_donation_tiers` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`amount` INT(11) NOT NULL DEFAULT 0, ' + - '`description` VARCHAR(255) NOT NULL, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofit_donation_tiers_nonprofit_id` (`nonprofitId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofits'); - - connection.query('CREATE TABLE `nonprofits` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`address1` VARCHAR(50) NOT NULL, ' + - '`address2` VARCHAR(50) NOT NULL, ' + - '`category1` INT(11) NOT NULL DEFAULT 0, ' + - '`category2` INT(11) NOT NULL DEFAULT 0, ' + - '`category3` INT(11) NOT NULL DEFAULT 0, ' + - '`city` VARCHAR(50) NOT NULL, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`phone` VARCHAR(50) NOT NULL, ' + - '`state` VARCHAR(50) NOT NULL, ' + - '`zip` VARCHAR(50) NOT NULL, ' + - '`legalName` VARCHAR(50) NOT NULL, ' + - '`legalNameSearch` VARCHAR(50) NOT NULL, ' + - '`logoFileId` INT(11) NOT NULL DEFAULT 0, ' + - '`longDescription` VARCHAR(255) NOT NULL, ' + - '`receiveDonationNotifications` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`shortDescription` VARCHAR(50) NOT NULL, ' + - '`slug` VARCHAR(50) NOT NULL, ' + - '`socialSharingDescription` VARCHAR(50) NOT NULL, ' + - '`socialSharingFileId` INT(11) NOT NULL DEFAULT 0, ' + - '`status` VARCHAR(50) NOT NULL, ' + - '`taxId` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofits_is_deleted` (`isDeleted`), ' + - 'KEY `ix_nonprofits_status_legal_name_search_is_deleted` (`status`, `legalNameSearch`, `isDeleted`), ' + - 'KEY `ix_nonprofits_slug` (`slug`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS nonprofit_slides'); - - connection.query('CREATE TABLE `nonprofit_slides` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`caption` VARCHAR(50) NOT NULL, ' + - '`embedUrl` VARCHAR(50) NOT NULL, ' + - '`externalId` VARCHAR(50) NOT NULL, ' + - '`thumbnail` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`url` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_nonprofit_slides_nonprofit_id` (`nonprofitId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS payment_transactions'); - - connection.query('CREATE TABLE `payment_transactions` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`billingZip` VARCHAR(50) NOT NULL, ' + - '`creditCardExpirationMonth` INT(11) NOT NULL DEFAULT 0, ' + - '`creditCardExpirationYear` INT(11) NOT NULL DEFAULT 0, ' + - '`creditCardLast4` VARCHAR(50) NOT NULL, ' + - '`creditCardName` VARCHAR(50) NOT NULL, ' + - '`creditCardType` VARCHAR(50) NOT NULL, ' + - '`isTestMode` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`transactionAmount` INT(11) NOT NULL DEFAULT 0, ' + - '`transactionId` VARCHAR(50) NOT NULL, ' + - '`transactionStatus` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS reports'); - - connection.query('CREATE TABLE `reports` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`status` VARCHAR(50) NOT NULL, ' + - '`type` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS settings'); - - connection.query('CREATE TABLE `settings` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`key` VARCHAR(50) NOT NULL, ' + - '`value` VARCHAR(50) NOT NULL, ' + - 'PRIMARY KEY (`id`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS sponsors'); - - connection.query('CREATE TABLE `sponsors` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`logoUrl` VARCHAR(50) NOT NULL, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - '`url` VARCHAR(50) NOT NULL, ' + - '`fileId` INT(11) NOT NULL DEFAULT 0, ' + - '`sponsorTierId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_sponsors_sponsor_tier_id` (`sponsorTierId`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS sponsor_tiers'); - - connection.query('CREATE TABLE `sponsor_tiers` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`name` VARCHAR(50) NOT NULL, ' + - '`size` VARCHAR(50) NOT NULL, ' + - '`sortOrder` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_sponsor_tiers_name` (`name`) ' + - ')'); - - connection.query('DROP TABLE IF EXISTS users'); - - connection.query('CREATE TABLE `users` ( ' + - '`id` INT(11) NOT NULL, ' + - '`createdOn` datetime NOT NULL DEFAULT \'0000-00-00 00:00:00\', ' + - '`isDeleted` TINYINT(1) NOT NULL DEFAULT 0, ' + - '`email` VARCHAR(50) NOT NULL, ' + - '`lastName` VARCHAR(50) NOT NULL, ' + - '`firstName` VARCHAR(50) NOT NULL, ' + - '`cognitoId` INT(11) NOT NULL DEFAULT 0, ' + - '`nonprofitId` INT(11) NOT NULL DEFAULT 0, ' + - 'PRIMARY KEY (`id`), ' + - 'KEY `ix_users_email` (`email`), ' + - 'KEY `ix_users_cognito_id` (`cognitoId`) ' + - ')'); - connection.end(); - - response.send(event, context, response.SUCCESS, {}); - callback(); - } - }).catch(function (err) { - console.log(err); - response.send(event, context, response.FAILED, {}); - callback(err); - }); -}; \ No newline at end of file diff --git a/packages/lambda/src/database/migrateDatabase/index.js b/packages/lambda/src/database/migrateDatabase/index.js new file mode 100644 index 00000000..150e8643 --- /dev/null +++ b/packages/lambda/src/database/migrateDatabase/index.js @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const fs = require('fs'); +const path = require('path'); +const logger = require('./../../helpers/log'); +const response = require('cfn-response'); +const Request = require('./../../aws/request'); +const S3 = require('./../../aws/s3'); +const SecretsManager = require('./../../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); +const Umzug = require('umzug'); + +exports.handle = function (event, context, callback) { + logger.log('migrateDatabase event: %j', event); + + const secretsManager = new SecretsManager(); + const request = new Request(event, context); + const s3 = new S3(); + const localPath = '/tmp'; + + if (event.RequestType === 'Delete') { + response.send(event, context, response.SUCCESS); + return; + } + + request.validate().then(function () { + fs.rmdirSync(path.join(localPath, process.env.MIGRATIONS_LOCATION), {recursive: true}); + return s3.listObjects(process.env.AWS_REGION, process.env.MIGRATIONS_BUCKET, process.env.MIGRATIONS_LOCATION).then(function (objects) { + return Promise.all(objects.map(function (obj) { + return s3.downloadObject(process.env.AWS_REGION, process.env.MIGRATIONS_BUCKET, obj.Key, localPath); + })); + }); + }).then(function () { + return secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID); + }).then(function (secret) { + const dbHost = process.env.DATABASE_HOST; + const dbName = process.env.DATABASE_NAME; + const maintenanceSecret = JSON.parse(secret.SecretString); + const sequelize = new Sequelize({ + host: dbHost, + username: maintenanceSecret.username, + password: maintenanceSecret.password, + database: dbName, + dialect: 'mysql', + dialectModule: mysql2, + port: 3306, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } + }); + + const umzug = new Umzug({ + migrations: { + path: path.join(localPath, process.env.MIGRATIONS_LOCATION), + params: [ + sequelize.getQueryInterface(), + Sequelize + ], + customResolver: function (filePath) { + return __non_webpack_require__(filePath); + }, + }, + storage: 'sequelize', + storageOptions: { + sequelize: sequelize + } + }) + + return umzug.up(); + }).then(function (migrations) { + logger.log("Ran migrations:" + migrations.map(it => { return it['file'] })); + response.send(event, context, response.SUCCESS, {}); + callback(); + }).catch(function (err) { + logger.log(err); + response.send(event, context, response.FAILED, {}); + callback(err); + }); +}; From 933940c72f3b559dff014d0ccd739d265e34883b Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 14 Aug 2020 17:37:03 +0000 Subject: [PATCH 040/140] WIP --- packages/lambda/src/models/connect.js | 63 ++++++++++++--------------- packages/lambda/src/models/index.js | 52 +++++----------------- packages/lambda/src/models/setting.js | 14 +++--- 3 files changed, 45 insertions(+), 84 deletions(-) diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index eb039cfd..40699c96 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -1,43 +1,36 @@ 'use strict'; -const fs = require('fs'); -const path = require('path'); -const CloudFormation = require('./../aws/cloudformation'); -const SecretsManager = require('./../aws/secretsManager'); +const CloudFormation = require('../aws/cloudformation'); +const SecretsManager = require('../aws/secretsManager'); const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); -console.log("IN CONNECT"); -function init() { - console.log("Getting stack " + process.env.AWS_STACK_NAME + " in region " + process.env.AWS_REGION); - - return new Sequelize({ - host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } +module.exports = function() { + const cloudFormation = new CloudFormation(); + //return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { + return cloudFormation.describeStacks('us-east-1', 'JOE-TEST').then(function (stacks) { + const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadwriteSecret').OutputValue; + const secretsManager = new SecretsManager(); + //return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); + return secretsManager.getSecretValue('us-east-1', secretId); + }).then(function (secret) { + const readwriteSecret = JSON.parse(secret.SecretString); + return new Sequelize({ + host: readwriteSecret.host, + username: readwriteSecret.username, + password: readwriteSecret.password, + database: readwriteSecret.database, + port: readwriteSecret.port, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS' + } + }); + }).then(function (sequelize) { + return sequelize; }); -} -const sequelize = new Sequelize({ - host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } -}); +}; -module.exports = {"sequelize": sequelize, "Sequelize": Sequelize}; diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js index 73bebb89..afcf17a6 100644 --- a/packages/lambda/src/models/index.js +++ b/packages/lambda/src/models/index.js @@ -2,45 +2,13 @@ const fs = require('fs'); const path = require('path'); -const Sequelize = require('sequelize'); -const basename = path.basename(__filename); -const db = {}; -const mysql2 = require('mysql2'); -const setting = require('./setting'); - -const sequelize = new Sequelize({ - host: 'dylan-test-two-auroradbstack-19x03f0xu-rdscluster-1bsdxanbndw2a.cluster-cdppswj4bvwh.us-east-1.rds.amazonaws.com', - username: 'readonly', - password: 'pL0CM[>)mrTjOr((R#]K>f+:p6m,Ha{`', - database: 'givesource', - port: 3306, - dialect: 'mysql', - dialectModule: mysql2, - ssl: true, - dialectOptions: { - ssl: 'Amazon RDS' - } -}); - -const models = [setting]; - -models.forEach(function (object) { - const model = require('./setting')(sequelize, Sequelize.DataTypes); - console.log('index model!'); /*DM: Debug */ - console.log(model); /*DM: Debug */ - db['Setting'] = model; -}); - -Object.keys(db).forEach(modelName => { - if (db[modelName].associate) { - db[modelName].associate(db); - } -}); -console.log('db equals: ', db); /*DM: Debug */ - -db.sequelize = sequelize; -db.Sequelize = Sequelize; - -console.log(db); /*DM: Debug */ - -module.exports = db; +const connect = require('./connect.js'); + +module.exports = function() { + return connect().then(function(sequelize) { + const models = {}; + const model = require('./setting')(sequelize); + models[model.name] = model; + return models; + }); +} diff --git a/packages/lambda/src/models/setting.js b/packages/lambda/src/models/setting.js index 4181d3ae..ad4a7e27 100644 --- a/packages/lambda/src/models/setting.js +++ b/packages/lambda/src/models/setting.js @@ -1,10 +1,10 @@ 'use strict'; -const { sequelize, Sequelize } = require('./connect'); +const { DataTypes } = require('sequelize'); -const Setting = sequelize.define('Setting', { - key: Sequelize.DataTypes.STRING, - value: Sequelize.DataTypes.STRING -}); - -console.log(Setting === sequelize.models.Setting); +module.exports = (sequelize) => { + return sequelize.define('Setting', { + key: DataTypes.STRING, + value: DataTypes.STRING + }); +}; From d6d2b05bb7cab851e7bbe8e501efea035276b5dc Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 14 Aug 2020 19:09:32 +0000 Subject: [PATCH 041/140] WIP --- packages/lambda/src/models/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js index afcf17a6..7813b58a 100644 --- a/packages/lambda/src/models/index.js +++ b/packages/lambda/src/models/index.js @@ -6,7 +6,7 @@ const connect = require('./connect.js'); module.exports = function() { return connect().then(function(sequelize) { - const models = {}; + const models = {"sequelize": sequelize}; const model = require('./setting')(sequelize); models[model.name] = model; return models; From 93fe88be050740c9f70f1495ad9ef9fd55be5a1a Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 14 Aug 2020 13:51:47 -0500 Subject: [PATCH 042/140] WIP --- packages/cloudformation/templates/givesource-aurora.yml | 2 +- packages/cloudformation/templates/givesource.yml | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index be78b133..c2fae0f4 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -138,7 +138,7 @@ Resources: AutoPause: true MaxCapacity: 16 MinCapacity: 1 - SecondsUntilAutoPause: 900 + SecondsUntilAutoPause: 14400 DBSubnetGroupName: !Ref DBSubnetGroup VpcSecurityGroupIds: - !GetAtt DBSecurityGroup.GroupId diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 12d1545d..5c6d2cda 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -777,9 +777,6 @@ Outputs: DatabaseReadwriteSecret: Value: !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecret - DatabaseReadonlySecret: - Value: !GetAtt AuroraDbStack.Outputs.ReadonlyUserSecret - PublicPagesCloudFrontDistribution: Value: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDistribution From e73ba044ed8af7d86fcd473c3e5b141fe0c13cc6 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 14 Aug 2020 21:15:08 +0000 Subject: [PATCH 043/140] WIP --- packages/lambda/src/models/connect.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index 40699c96..dfbfd72c 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -25,7 +25,8 @@ module.exports = function() { dialectModule: mysql2, ssl: true, dialectOptions: { - ssl: 'Amazon RDS' + ssl: 'Amazon RDS', + connectTimeout: 60000 } }); }).then(function (sequelize) { From 8965836ea0df8c9ef30ed44da1fe53362be2b495 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 17 Aug 2020 09:39:43 -0500 Subject: [PATCH 044/140] GD-1640: Update the settings repository (moved models, trying to get setting.js to connect with findAll()) --- .../templates/givesource-api-settings.yml | 51 +++++++++++++++++++ .../cloudformation/templates/givesource.yml | 2 + packages/lambda/src/api/getSettings/index.js | 29 +++++++---- .../lambda/src/api/patchSettings/index.js | 50 +++++++++++------- packages/lambda/src/api/postSetting/index.js | 30 ++++++----- packages/lambda/src/models/connect.js | 3 +- packages/lambda/src/models/setting.js | 12 ++++- 7 files changed, 135 insertions(+), 42 deletions(-) diff --git a/packages/cloudformation/templates/givesource-api-settings.yml b/packages/cloudformation/templates/givesource-api-settings.yml index c15a2936..4eb76e5f 100644 --- a/packages/cloudformation/templates/givesource-api-settings.yml +++ b/packages/cloudformation/templates/givesource-api-settings.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -96,6 +99,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -125,6 +134,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -154,6 +169,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -183,6 +204,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -212,6 +239,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -241,6 +274,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -393,6 +432,12 @@ Resources: Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -420,6 +465,12 @@ Resources: Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 5c6d2cda..eacf9554 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -406,6 +406,7 @@ Resources: Service: - lambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref CloudWatchLogsManagedPolicy - !Ref SSMManagedPolicy - !Ref SecureSettingsEncryptManagedPolicy @@ -625,6 +626,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] diff --git a/packages/lambda/src/api/getSettings/index.js b/packages/lambda/src/api/getSettings/index.js index 07d7cb5e..6db5ef40 100644 --- a/packages/lambda/src/api/getSettings/index.js +++ b/packages/lambda/src/api/getSettings/index.js @@ -16,24 +16,35 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const SettingsRepository = require('./../../repositories/settings'); -const Setting = require('./../../models/index').Setting; +const Sequelize = require('sequelize'); +const loadModels = require('./../../models/index'); exports.handle = function (event, context, callback) { - const repository = new SettingsRepository(); const request = new Request(event, context); const keys = request.queryParam('keys', '').split(','); + let allModels; request.validate().then(function () { - console.log("KEYS ARE "); - console.log(keys); - console.log(Setting); /*DM: Debug */ - return Setting.findAll(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + if (keys.length) { + return allModels.Setting.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } + } + }); + } else { + return allModels.Setting.findAll(); + } + }); }).then(function (settings) { - console.log("SETTINGS ARE "); - console.log(settings); callback(null, settings); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index 627b8559..631ba5a9 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -15,46 +15,58 @@ */ const _ = require('lodash'); +const Sequelize = require('sequelize'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; + let allModels; request.validate().then(function () { const keys = request.get('settings', []).map(function (setting) { return setting.key; }); - return repository.batchGet(keys).then(function (models) { - request.get('settings', []).forEach(function (data) { - let model = _.find(models, {key: data.key}); - if (model) { - model.populate(data); - } else { - model = new Setting(data); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } } - - settings.push(model); }); }); - }).then(function () { + }).then(function (models) { + request.get('settings', []).forEach(function (data) { + let model = _.find(models, {key: data.key}); + if (model instanceof allModels.Setting) { + model.set('value', data.value); + settings.push(model); + } else { + settings.push(new allModels.Setting(data)); + } + }); + + return settings; + }).then(function (settings) { let promise = Promise.resolve(); settings.forEach(function (setting) { - promise = promise.then(function () { - return setting.validate(); - }); + if (setting instanceof allModels.Setting) { + promise = promise.then(function () { + return allModels.Setting.upsert(setting.toJSON()); + }); + } }); + return promise; - }).then(function () { - return repository.batchUpdate(settings); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -63,5 +75,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index f6b6603f..d40b900f 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -18,37 +18,43 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const ResourceAlreadyExistsException = require('./../../exceptions/resourceAlreadyExists'); -const Setting = require('../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let setting = new Setting(request._body); + let setting; + let allModels; request.validate().then(function () { return new Promise(function (resolve, reject) { - repository.get(request.get('key')).then(function () { - reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); - }).catch(function () { - resolve(); + loadModels().then(function (models) { + allModels = models; + setting = new allModels.Setting(request._body); + }).then(function () { + return allModels.Setting.findOne({key: request.get('key')}); + }).then(function (setting) { + if (setting instanceof allModels.Setting) { + reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); + } else { + resolve(); + } }); }); }).then(function () { - return setting.validate(); - }).then(function () { - return repository.save(setting); + return allModels.Setting.create(setting.toJSON()); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { return DynamicContentHelper.regenerateDynamicContent([setting.key], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); }).then(function () { - callback(null, setting.all()); + callback(null, setting); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index dfbfd72c..3d873e14 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -8,7 +8,8 @@ const Sequelize = require('sequelize'); module.exports = function() { const cloudFormation = new CloudFormation(); //return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { - return cloudFormation.describeStacks('us-east-1', 'JOE-TEST').then(function (stacks) { + // return cloudFormation.describeStacks('us-east-1', 'JOE-TEST').then(function (stacks) { + return cloudFormation.describeStacks('us-east-1', 'DYLAN-TEST-TWO').then(function (stacks) { const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadwriteSecret').OutputValue; const secretsManager = new SecretsManager(); //return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); diff --git a/packages/lambda/src/models/setting.js b/packages/lambda/src/models/setting.js index ad4a7e27..39296147 100644 --- a/packages/lambda/src/models/setting.js +++ b/packages/lambda/src/models/setting.js @@ -4,7 +4,15 @@ const { DataTypes } = require('sequelize'); module.exports = (sequelize) => { return sequelize.define('Setting', { - key: DataTypes.STRING, - value: DataTypes.STRING + key: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true + } + }, + value: { + type: DataTypes.STRING, + } }); }; From 56c5bedfaffe163593a60c793032d14a9fb201e2 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Mon, 17 Aug 2020 11:22:10 -0500 Subject: [PATCH 045/140] WIP --- packages/lambda/migrations/00_initial.js | 2 +- .../lambda/src/database/bootstrapDatabase/index.js | 11 ++++++++--- packages/lambda/src/models/connect.js | 9 ++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 3bc1d6cb..08d67851 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -654,7 +654,7 @@ module.exports = { allowNull: false }, value: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false }, isDeleted: { diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js index 98e9eda9..1f739dce 100644 --- a/packages/lambda/src/database/bootstrapDatabase/index.js +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -32,6 +32,7 @@ exports.handle = function (event, context, callback) { return; } + let sequelize; request.validate().then(function () { return Promise.all([ secretsManager.getSecretValue(process.env.AWS_REGION, process.env.ADMIN_DATABASE_SECRET_ID), @@ -47,13 +48,13 @@ exports.handle = function (event, context, callback) { const readwriteSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READWRITE_DATABASE_SECRET_ID).SecretString); const readonlySecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READONLY_DATABASE_SECRET_ID).SecretString); - const sequelize = new Sequelize({ - host: dbHost, + sequelize = new Sequelize({ + host: adminSecret.host, username: adminSecret.username, password: adminSecret.password, + port: adminSecret.port, dialect: 'mysql', dialectModule: mysql2, - port: 3306, logging: false, // don't log the sql so we don't log the passwords ssl: true, dialectOptions: { @@ -79,5 +80,9 @@ exports.handle = function (event, context, callback) { logger.log(err); response.send(event, context, response.FAILED); callback(err); + }).finally(function() { + if (sequelize) { + sequelize.close(); + } }); }; diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index 3d873e14..5d022256 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -7,13 +7,10 @@ const Sequelize = require('sequelize'); module.exports = function() { const cloudFormation = new CloudFormation(); - //return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { - // return cloudFormation.describeStacks('us-east-1', 'JOE-TEST').then(function (stacks) { - return cloudFormation.describeStacks('us-east-1', 'DYLAN-TEST-TWO').then(function (stacks) { + return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadwriteSecret').OutputValue; const secretsManager = new SecretsManager(); - //return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); - return secretsManager.getSecretValue('us-east-1', secretId); + return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); }).then(function (secret) { const readwriteSecret = JSON.parse(secret.SecretString); return new Sequelize({ @@ -33,6 +30,4 @@ module.exports = function() { }).then(function (sequelize) { return sequelize; }); - }; - From d05e43deb876f749191eab04ae98eb6846d39d21 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 17 Aug 2020 15:25:59 -0500 Subject: [PATCH 046/140] GD-1640: Update the settings repository (moved models, trying to get setting.js to connect with findAll()) --- .../lambda/src/api/deleteSetting/index.js | 16 ++++++++-- .../lambda/src/api/deleteSettings/index.js | 30 ++++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/lambda/src/api/deleteSetting/index.js b/packages/lambda/src/api/deleteSetting/index.js index 88a7cf84..83e71233 100644 --- a/packages/lambda/src/api/deleteSetting/index.js +++ b/packages/lambda/src/api/deleteSetting/index.js @@ -17,17 +17,25 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); +const loadModels = require('./../../models/index'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); + let allModels; request.validate().then(function () { - return repository.delete(request.urlParam('key')); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Settings.destroy({ + where: { + key: request.urlParam('key') + } + }) + }); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -36,5 +44,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; \ No newline at end of file diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index d00c3f9a..17cc76eb 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -17,30 +17,30 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { - const repository = new SettingsRepository(); + const lambda = new Lambda(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; + let allModels; request.validate().then(function () { - request.get('settings', []).forEach(function (data) { - settings.push(new Setting(data)); - }); - }).then(function () { - let promise = Promise.resolve(); - settings.forEach(function (setting) { - promise = promise.then(function () { - return setting.validate(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + request.get('settings', []).forEach(function (data) { + let promise = Promise.resolve(); + promise.then(function () { + return allModels.Setting.findOne(data).then(function (setting) { + settings.push(setting); + return setting.destroy(); + }); + }); }); }); - return promise; - }).then(function () { - return repository.batchDeleteByKey(settings); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -49,5 +49,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; From a09b9a9a110a6043f03277405953f80fa7c352b2 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 18 Aug 2020 07:21:50 -0500 Subject: [PATCH 047/140] WIP --- .../templates/givesource-aurora.yml | 34 +++---------------- .../cloudformation/templates/givesource.yml | 2 +- .../src/database/bootstrapDatabase/index.js | 8 ++--- 3 files changed, 7 insertions(+), 37 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index c2fae0f4..3dc1b928 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -26,14 +26,6 @@ Parameters: MinLength: '1' Type: String Default: readwrite - DatabaseReadonlyUser: - AllowedPattern: "[a-zA-Z0-9_]+" - ConstraintDescription: must be between 1 to 16 alphanumeric characters. - Description: The database readonly account user name, between 1 to 16 alphanumeric characters. - MaxLength: '16' - MinLength: '1' - Type: String - Default: readonly DatabaseName: Type: String Default: givesource @@ -107,22 +99,6 @@ Resources: SecretId: !Ref ReadwriteUserSecret TargetId: !Ref RDSCluster TargetType: AWS::RDS::DBCluster - ReadonlyUserSecret: - Type: AWS::SecretsManager::Secret - Properties: - Name: !Sub ${AWS::StackName}-ReadonlyUserSecret - Description: Givesource database auto-generated readonly user password - GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}", "database": "${DatabaseName}"}' - GenerateStringKey: password - PasswordLength: 32 - ExcludeCharacters: '"@/\' - ReadonlyUserSecretAttachment: - Type: AWS::SecretsManager::SecretTargetAttachment - Properties: - SecretId: !Ref ReadonlyUserSecret - TargetId: !Ref RDSCluster - TargetType: AWS::RDS::DBCluster RDSCluster: Type: AWS::RDS::DBCluster Properties: @@ -175,7 +151,6 @@ Resources: - !Ref AdminUserSecret - !Ref MaintenanceUserSecret - !Ref ReadwriteUserSecret - - !Ref ReadonlyUserSecret ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole BootstrapDatabaseLambdaFunction: @@ -193,7 +168,6 @@ Resources: ADMIN_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-AdminUserSecret MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret READWRITE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadwriteUserSecret - READONLY_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadonlyUserSecret DATABASE_NAME: !Ref DatabaseName FunctionName: !Sub ${StackName}-BootstrapDatabase Handler: index.handle @@ -207,11 +181,14 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DependsOn: RDSCluster BootstrapDatabaseLambdaLambdaInvoker: Type: Custom::BootstrapDatabaseLambdaInvoker Properties: ServiceToken: !GetAtt BootstrapDatabaseLambdaFunction.Arn + DependsOn: + - AdminUserSecretAttachment + - MaintenanceUserSecretAttachment + - ReadwriteUserSecretAttachment MigrateDatabaseLambdaRole: Type: AWS::IAM::Role Properties: @@ -273,7 +250,6 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DependsOn: RDSCluster MigrateDatabaseLambdaLambdaInvoker: Type: Custom::MigrateDatabaseLambdaInvoker Properties: @@ -282,8 +258,6 @@ Resources: Outputs: ReadwriteUserSecret: Value: !Sub ${AWS::StackName}-ReadwriteUserSecret - ReadonlyUserSecret: - Value: !Sub ${AWS::StackName}-ReadonlyUserSecret DatabaseClusterArn: Value: !Ref RDSCluster DatabaseEndpoint: diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index eacf9554..bec23d3c 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -310,7 +310,7 @@ Resources: - secretsmanager:GetSecretValue Resource: '*' # Resource: -# - !Ref ReadonlyUserSecret +# - !Ref ReadwriteUserSecret LambdaRole: Type: AWS::IAM::Role diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js index 1f739dce..47c6e47e 100644 --- a/packages/lambda/src/database/bootstrapDatabase/index.js +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -37,8 +37,7 @@ exports.handle = function (event, context, callback) { return Promise.all([ secretsManager.getSecretValue(process.env.AWS_REGION, process.env.ADMIN_DATABASE_SECRET_ID), secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID), - secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID), - secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READONLY_DATABASE_SECRET_ID) + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID) ]); }).then(function (secrets) { const dbHost = process.env.DATABASE_HOST; @@ -46,7 +45,6 @@ exports.handle = function (event, context, callback) { const adminSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.ADMIN_DATABASE_SECRET_ID).SecretString); const maintenanceSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.MAINTENANCE_DATABASE_SECRET_ID).SecretString); const readwriteSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READWRITE_DATABASE_SECRET_ID).SecretString); - const readonlySecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READONLY_DATABASE_SECRET_ID).SecretString); sequelize = new Sequelize({ host: adminSecret.host, @@ -69,9 +67,7 @@ exports.handle = function (event, context, callback) { 'CREATE USER IF NOT EXISTS "' + maintenanceSecret.username + '"@"%" IDENTIFIED BY "' + maintenanceSecret.password + '"; ' + 'GRANT ALL PRIVILEGES ON `' + dbName+ '`.* TO "' + maintenanceSecret.username + '"@"%"; ' + 'CREATE USER IF NOT EXISTS "' + readwriteSecret.username + '"@"%" IDENTIFIED BY "' + readwriteSecret.password + '"; ' + - 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%"; ' + - 'CREATE USER IF NOT EXISTS "' + readonlySecret.username + '"@"%" IDENTIFIED BY "' + readonlySecret.password + '"; ' + - 'GRANT SELECT ON `' + dbName+ '`.* TO "' + readonlySecret.username + '"@"%";' + 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%";' ); }).then(function () { response.send(event, context, response.SUCCESS); From 3668a2eb15af9c025752a91df4fa559e1473e361 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Fri, 21 Aug 2020 13:57:42 -0500 Subject: [PATCH 048/140] [GD-1640] Update the settings repository * Added SecurityGroup and Subnet config to settings lambda * Added schema for all tables * Renamed dynamo models * Updated settings to use new sequelize model * Improved sequelize connect and model load logic --- .../templates/givesource-api-settings.yml | 51 ++ .../templates/givesource-aurora.yml | 65 +- .../cloudformation/templates/givesource.yml | 22 + packages/lambda/bin/delete-test-payments.js | 2 +- packages/lambda/migrations/00_initial.js | 805 +++++++++++++++++- .../src/api/adminRegisterNonprofit/index.js | 4 +- .../lambda/src/api/deleteContents/index.js | 2 +- packages/lambda/src/api/deleteFiles/index.js | 2 +- .../lambda/src/api/deleteMetrics/index.js | 2 +- .../api/deleteNonprofitDonationTiers/index.js | 2 +- .../lambda/src/api/deleteSetting/index.js | 16 +- .../lambda/src/api/deleteSettings/index.js | 32 +- .../lambda/src/api/deleteSponsors/index.js | 2 +- packages/lambda/src/api/getSetting/index.js | 2 +- packages/lambda/src/api/getSettings/index.js | 34 +- packages/lambda/src/api/patchContent/index.js | 2 +- .../lambda/src/api/patchContents/index.js | 2 +- .../lambda/src/api/patchDonation/index.js | 2 +- packages/lambda/src/api/patchMessage/index.js | 2 +- packages/lambda/src/api/patchMetrics/index.js | 2 +- .../lambda/src/api/patchNonprofit/index.js | 2 +- .../src/api/patchNonprofitDonation/index.js | 2 +- .../api/patchNonprofitDonationTiers/index.js | 2 +- .../src/api/patchNonprofitSlide/index.js | 2 +- .../src/api/patchNonprofitSlides/index.js | 2 +- .../src/api/patchNonprofitStatus/index.js | 2 +- .../src/api/patchPaymentTransaction/index.js | 2 +- packages/lambda/src/api/patchSetting/index.js | 2 +- .../lambda/src/api/patchSettings/index.js | 52 +- packages/lambda/src/api/patchSponsor/index.js | 2 +- .../lambda/src/api/patchSponsorTier/index.js | 2 +- .../lambda/src/api/patchSponsorTiers/index.js | 2 +- .../lambda/src/api/patchSponsors/index.js | 2 +- packages/lambda/src/api/patchUser/index.js | 2 +- packages/lambda/src/api/postContent/index.js | 2 +- packages/lambda/src/api/postDonation/index.js | 2 +- packages/lambda/src/api/postDonor/index.js | 2 +- packages/lambda/src/api/postFile/index.js | 2 +- packages/lambda/src/api/postMessage/index.js | 2 +- .../lambda/src/api/postNonprofit/index.js | 2 +- .../src/api/postNonprofitDonation/index.js | 2 +- .../api/postNonprofitDonationTier/index.js | 2 +- .../src/api/postNonprofitReport/index.js | 2 +- .../src/api/postNonprofitSlide/index.js | 2 +- .../lambda/src/api/postNonprofitUser/index.js | 2 +- .../src/api/postPaymentTransaction/index.js | 2 +- packages/lambda/src/api/postReport/index.js | 2 +- packages/lambda/src/api/postSetting/index.js | 32 +- packages/lambda/src/api/postSponsor/index.js | 2 +- .../lambda/src/api/postSponsorTier/index.js | 2 +- packages/lambda/src/api/postUser/index.js | 2 +- .../lambda/src/api/processDonations/index.js | 6 +- .../lambda/src/api/registerNonprofit/index.js | 4 +- .../api/resendUserEmailVerification/index.js | 2 +- packages/lambda/src/aws/cloudformation.js | 39 + .../src/custom/cognitoCreateUser/index.js | 2 +- .../custom/generateDonationsReceipt/index.js | 6 +- .../lambda/src/custom/generateReport/index.js | 6 +- .../src/custom/metricAddAmount/index.js | 2 +- .../src/custom/metricMaxAmount/index.js | 2 +- .../lambda/src/custom/saveSettings/index.js | 4 +- .../sendDonationNotificationEmail/index.js | 2 +- .../src/database/bootstrapDatabase/index.js | 19 +- .../src/{models => dynamo-models}/content.js | 0 .../src/{models => dynamo-models}/donation.js | 0 .../src/{models => dynamo-models}/donor.js | 0 .../src/{models => dynamo-models}/file.js | 0 .../src/{models => dynamo-models}/message.js | 0 .../src/{models => dynamo-models}/metric.js | 0 .../src/{models => dynamo-models}/model.js | 0 .../{models => dynamo-models}/nonprofit.js | 0 .../nonprofitDonationTier.js | 0 .../nonprofitSlide.js | 0 .../paymentTransaction.js | 0 .../src/{models => dynamo-models}/report.js | 0 .../src/{models => dynamo-models}/sponsor.js | 0 .../{models => dynamo-models}/sponsorTier.js | 0 .../src/{models => dynamo-models}/user.js | 0 packages/lambda/src/helpers/generator.js | 2 +- packages/lambda/src/models/connect.js | 49 ++ packages/lambda/src/models/index.js | 30 + packages/lambda/src/models/setting.js | 57 +- packages/lambda/src/repositories/contents.js | 2 +- packages/lambda/src/repositories/donations.js | 2 +- packages/lambda/src/repositories/donors.js | 2 +- packages/lambda/src/repositories/files.js | 2 +- packages/lambda/src/repositories/messages.js | 2 +- packages/lambda/src/repositories/metrics.js | 2 +- .../repositories/nonprofitDonationTiers.js | 2 +- .../src/repositories/nonprofitDonations.js | 2 +- .../src/repositories/nonprofitReports.js | 2 +- .../src/repositories/nonprofitSlides.js | 2 +- .../lambda/src/repositories/nonprofitUsers.js | 2 +- .../lambda/src/repositories/nonprofits.js | 2 +- .../src/repositories/paymentTransactions.js | 2 +- packages/lambda/src/repositories/reports.js | 2 +- .../lambda/src/repositories/repository.js | 2 +- packages/lambda/src/repositories/settings.js | 31 +- .../lambda/src/repositories/sponsorTiers.js | 2 +- packages/lambda/src/repositories/sponsors.js | 2 +- packages/lambda/src/repositories/users.js | 2 +- packages/lambda/test/models/donation.js | 4 +- packages/lambda/test/models/donor.js | 4 +- packages/lambda/test/models/file.js | 4 +- packages/lambda/test/models/message.js | 4 +- packages/lambda/test/models/metric.js | 4 +- packages/lambda/test/models/model.js | 2 +- packages/lambda/test/models/nonprofit.js | 4 +- packages/lambda/test/models/nonprofitSlide.js | 4 +- .../lambda/test/models/paymentTransaction.js | 4 +- packages/lambda/test/models/report.js | 4 +- packages/lambda/test/models/setting.js | 4 +- packages/lambda/test/models/sponsor.js | 4 +- packages/lambda/test/models/sponsorTier.js | 4 +- packages/lambda/test/models/user.js | 4 +- .../lambda/test/repositories/donations.js | 2 +- packages/lambda/test/repositories/donors.js | 2 +- packages/lambda/test/repositories/messages.js | 2 +- packages/lambda/test/repositories/metrics.js | 2 +- .../test/repositories/nonprofitSlides.js | 2 +- .../lambda/test/repositories/nonprofits.js | 2 +- .../test/repositories/paymentTransactions.js | 2 +- packages/lambda/test/repositories/reports.js | 2 +- packages/lambda/test/repositories/settings.js | 2 +- .../lambda/test/repositories/sponsorTiers.js | 2 +- packages/lambda/test/repositories/sponsors.js | 2 +- packages/lambda/test/repositories/users.js | 2 +- 127 files changed, 1215 insertions(+), 357 deletions(-) create mode 100644 packages/lambda/src/aws/cloudformation.js rename packages/lambda/src/{models => dynamo-models}/content.js (100%) rename packages/lambda/src/{models => dynamo-models}/donation.js (100%) rename packages/lambda/src/{models => dynamo-models}/donor.js (100%) rename packages/lambda/src/{models => dynamo-models}/file.js (100%) rename packages/lambda/src/{models => dynamo-models}/message.js (100%) rename packages/lambda/src/{models => dynamo-models}/metric.js (100%) rename packages/lambda/src/{models => dynamo-models}/model.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofit.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofitDonationTier.js (100%) rename packages/lambda/src/{models => dynamo-models}/nonprofitSlide.js (100%) rename packages/lambda/src/{models => dynamo-models}/paymentTransaction.js (100%) rename packages/lambda/src/{models => dynamo-models}/report.js (100%) rename packages/lambda/src/{models => dynamo-models}/sponsor.js (100%) rename packages/lambda/src/{models => dynamo-models}/sponsorTier.js (100%) rename packages/lambda/src/{models => dynamo-models}/user.js (100%) create mode 100644 packages/lambda/src/models/connect.js create mode 100644 packages/lambda/src/models/index.js diff --git a/packages/cloudformation/templates/givesource-api-settings.yml b/packages/cloudformation/templates/givesource-api-settings.yml index c15a2936..4eb76e5f 100644 --- a/packages/cloudformation/templates/givesource-api-settings.yml +++ b/packages/cloudformation/templates/givesource-api-settings.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -96,6 +99,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -125,6 +134,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -154,6 +169,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -183,6 +204,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -212,6 +239,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -241,6 +274,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -393,6 +432,12 @@ Resources: Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -420,6 +465,12 @@ Resources: Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 7820ed3e..3dc1b928 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -26,14 +26,6 @@ Parameters: MinLength: '1' Type: String Default: readwrite - DatabaseReadonlyUser: - AllowedPattern: "[a-zA-Z0-9_]+" - ConstraintDescription: must be between 1 to 16 alphanumeric characters. - Description: The database readonly account user name, between 1 to 16 alphanumeric characters. - MaxLength: '16' - MinLength: '1' - Type: String - Default: readonly DatabaseName: Type: String Default: givesource @@ -65,7 +57,7 @@ Resources: Name: !Sub ${AWS::StackName}-AdminUserSecret Description: Givesource database auto-generated admin user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: '"@/\' @@ -81,7 +73,7 @@ Resources: Name: !Sub ${AWS::StackName}-MaintenanceUserSecret Description: Givesource database auto-generated maintenance user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: '"@/\' @@ -97,7 +89,7 @@ Resources: Name: !Sub ${AWS::StackName}-ReadwriteUserSecret Description: Givesource database auto-generated readwrite user password GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}"}' + SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}", "database": "${DatabaseName}"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: '"@/\' @@ -107,22 +99,6 @@ Resources: SecretId: !Ref ReadwriteUserSecret TargetId: !Ref RDSCluster TargetType: AWS::RDS::DBCluster - ReadonlyUserSecret: - Type: AWS::SecretsManager::Secret - Properties: - Name: !Sub ${AWS::StackName}-ReadonlyUserSecret - Description: Givesource database auto-generated readonly user password - GenerateSecretString: - SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}"}' - GenerateStringKey: password - PasswordLength: 32 - ExcludeCharacters: '"@/\' - ReadonlyUserSecretAttachment: - Type: AWS::SecretsManager::SecretTargetAttachment - Properties: - SecretId: !Ref ReadonlyUserSecret - TargetId: !Ref RDSCluster - TargetType: AWS::RDS::DBCluster RDSCluster: Type: AWS::RDS::DBCluster Properties: @@ -138,7 +114,7 @@ Resources: AutoPause: true MaxCapacity: 16 MinCapacity: 1 - SecondsUntilAutoPause: 900 + SecondsUntilAutoPause: 14400 DBSubnetGroupName: !Ref DBSubnetGroup VpcSecurityGroupIds: - !GetAtt DBSecurityGroup.GroupId @@ -175,7 +151,6 @@ Resources: - !Ref AdminUserSecret - !Ref MaintenanceUserSecret - !Ref ReadwriteUserSecret - - !Ref ReadonlyUserSecret ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole BootstrapDatabaseLambdaFunction: @@ -193,7 +168,6 @@ Resources: ADMIN_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-AdminUserSecret MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret READWRITE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadwriteUserSecret - READONLY_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadonlyUserSecret DATABASE_NAME: !Ref DatabaseName FunctionName: !Sub ${StackName}-BootstrapDatabase Handler: index.handle @@ -207,11 +181,14 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DependsOn: RDSCluster BootstrapDatabaseLambdaLambdaInvoker: Type: Custom::BootstrapDatabaseLambdaInvoker Properties: ServiceToken: !GetAtt BootstrapDatabaseLambdaFunction.Arn + DependsOn: + - AdminUserSecretAttachment + - MaintenanceUserSecretAttachment + - ReadwriteUserSecretAttachment MigrateDatabaseLambdaRole: Type: AWS::IAM::Role Properties: @@ -273,39 +250,15 @@ Resources: SubnetIds: - !ImportValue givsource-primary-private-subnet - !ImportValue givesource-secondary-private-subnet - DependsOn: RDSCluster MigrateDatabaseLambdaLambdaInvoker: Type: Custom::MigrateDatabaseLambdaInvoker Properties: ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn DependsOn: BootstrapDatabaseLambdaLambdaInvoker Outputs: - StackName: - Description: Aurora Stack Name - Value: !Ref AWS::StackName - Export: - Name: !Sub ${AWS::StackName}-StackName - - ReadwriteUserSecretId: - Description: Secret Id for the readwrite user + ReadwriteUserSecret: Value: !Sub ${AWS::StackName}-ReadwriteUserSecret - Export: - Name: !Sub ${AWS::StackName}-ReadwriteUserSecretId - - ReadonlyUserSecretId: - Description: Secret Id for the readonly user - Value: !Sub ${AWS::StackName}-ReadonlyUserSecret - Export: - Name: !Sub ${AWS::StackName}-UserSecretId - DatabaseClusterArn: - Description: Aurora Cluster ARN Value: !Ref RDSCluster - Export: - Name: !Sub ${AWS::StackName}-DatabaseClusterArn - DatabaseEndpoint: - Description: Aurora Database Endpoint Value: !GetAtt RDSCluster.Endpoint.Address - Export: - Name: !Sub ${AWS::StackName}-DatabaseEndpoint diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 50cc7f04..646b2f6c 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -111,6 +111,22 @@ Resources: TimeoutInMinutes: 40 DependsOn: LambdaSecurityGroup + SecretsManagerPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: readwrite_user_secret_get + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Sub arn:aws:secretsmanager:::secret:${AuroraDbStack.Outputs.ReadwriteUserSecret} + Roles: + - !Ref LambdaRole + DependsOn: AuroraDbStack + S3Stack: Type: AWS::CloudFormation::Stack Properties: @@ -316,6 +332,7 @@ Resources: - lambda.amazonaws.com - edgelambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref ApiGatewayManagedPolicy - !Ref CloudFormationManagedPolicy - !Ref CloudWatchLogsManagedPolicy @@ -397,6 +414,7 @@ Resources: Service: - lambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref CloudWatchLogsManagedPolicy - !Ref SSMManagedPolicy - !Ref SecureSettingsEncryptManagedPolicy @@ -616,6 +634,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -765,6 +784,9 @@ Outputs: LambdaRoleArn: Value: !GetAtt LambdaRole.Arn + DatabaseReadwriteSecret: + Value: !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecret + PublicPagesCloudFrontDistribution: Value: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDistribution diff --git a/packages/lambda/bin/delete-test-payments.js b/packages/lambda/bin/delete-test-payments.js index 7bfa2146..3db92fd9 100644 --- a/packages/lambda/bin/delete-test-payments.js +++ b/packages/lambda/bin/delete-test-payments.js @@ -17,7 +17,7 @@ require('./config/bootstrap').bootstrap(); const config = require('config'); -const Donation = require('./../src/models/donation'); +const Donation = require('./../src/dynamo-models/donation'); const DonationsRepository = require('./../src/repositories/donations'); const inquirer = require('inquirer'); const QueryBuilder = require('./../src/aws/queryBuilder'); diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 25594895..08d67851 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -2,74 +2,795 @@ module.exports = { up: async (queryInterface, Sequelize) => { - await queryInterface.createTable('Settings', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - key: { - type: Sequelize.STRING - }, - value: { - type: Sequelize.STRING - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - }, - isDeleted: { - type: Sequelize.BOOLEAN, - defaultValue: false, - allowNull: false - } - }).then( + await Promise.all([ queryInterface.createTable('Contents', { id: { + type: Sequelize.INTEGER(11), allowNull: false, autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER + primaryKey: true + }, + parentId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + value: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, }, createdAt: { + type: Sequelize.DATE, allowNull: false, - type: Sequelize.DATE + defaultValue: '0000-00-00 00:00:00' }, updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Donations', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + amountForNonprofit: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + count: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + fees: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isAnonymous: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + isFeeCovered: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + isOfflineDonation: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + paymentTransactionIsTestMode: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + paymentTransactionId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + subtotal: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + subtotalChargedToCard: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + total: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + type: { + type: Sequelize.TINYINT(1), + allowNull: false, + defaultValue: 0 + }, + donorId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + name: { + type: Sequelize.STRING(255), allowNull: false, - type: Sequelize.DATE }, isDeleted: { type: Sequelize.BOOLEAN, + allowNull: false, defaultValue: false, - allowNull: false }, - parentId: { - type: Sequelize.INTEGER + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Donors', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + amountForNonprofit: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + address1: { + type: Sequelize.STRING(50), + allowNull: false, + }, + address2: { + type: Sequelize.STRING(50), + allowNull: false, + }, + city: { + type: Sequelize.STRING(50), + allowNull: false, + }, + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + firstName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + lastName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + state: { + type: Sequelize.STRING(50), + allowNull: false, + }, + zip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Files', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + path: { + type: Sequelize.STRING(50), + allowNull: false, + }, + filename: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Messages', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + message: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Metrics', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + key: { + type: Sequelize.STRING(50), + allowNull: false, + }, + value: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('NonprofitDonationTiers', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + amount: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + value: { + type: Sequelize.STRING(255), + allowNull: false, + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Nonprofits', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + address1: { + type: Sequelize.STRING(50), + allowNull: false, + }, + address2: { + type: Sequelize.STRING(50), + allowNull: false, + }, + category1: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + category2: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + category3: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + city: { + type: Sequelize.STRING(50), + allowNull: false, + }, + email: { + type: Sequelize.STRING(50), + allowNull: false, + }, + firstName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + lastName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + phone: { + type: Sequelize.STRING(50), + allowNull: false, + }, + state: { + type: Sequelize.STRING(50), + allowNull: false, + }, + zip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + legalName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + legalNameSearch: { + type: Sequelize.STRING(50), + allowNull: false, + }, + logoFileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + longDescription: { + type: Sequelize.STRING(255), + allowNull: false, + }, + category3: { + type: Sequelize.TINYINT(1), + allowNull: false, + defaultValue: 0 + }, + shortDescription: { + type: Sequelize.STRING(50), + allowNull: false, + }, + slug: { + type: Sequelize.STRING(50), + allowNull: false, + }, + socialSharingDescription: { + type: Sequelize.STRING(50), + allowNull: false, + }, + socialSharingFileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + status: { + type: Sequelize.STRING(50), + allowNull: false, + }, + taxId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('NonprofitSlides', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true }, sortOrder: { - type: Sequelize.INTEGER + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + caption: { + type: Sequelize.STRING(50), + allowNull: false, + }, + embedUrl: { + type: Sequelize.STRING(50), + allowNull: false, + }, + externalId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + thumbnail: { + type: Sequelize.STRING(50), + allowNull: false, }, type: { - type: Sequelize.STRING + type: Sequelize.STRING(50), + allowNull: false, + }, + url: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('PaymentTransactions', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + billingZip: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardExpirationMonth: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + creditCardExpirationYear: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + creditCardLast4: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardName: { + type: Sequelize.STRING(50), + allowNull: false, + }, + creditCardType: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isTestMode: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + transactionAmount: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + transactionId: { + type: Sequelize.STRING(50), + allowNull: false, + }, + transactionStatus: { + type: Sequelize.STRING(50), + allowNull: false, + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Reports', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + status: { + type: Sequelize.STRING(50), + allowNull: false, + }, + type: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Settings', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + key: { + type: Sequelize.STRING(50), + allowNull: false }, value: { - type: Sequelize.STRING + type: Sequelize.STRING(2048), + allowNull: false + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('Sponsors', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + logoUrl: { + type: Sequelize.STRING(50), + allowNull: false, }, name: { - type: Sequelize.STRING + type: Sequelize.STRING(50), + allowNull: false, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + url: { + type: Sequelize.STRING(50), + allowNull: false, + }, + fileId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + sponsorTierId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } + }), + queryInterface.createTable('SponsorTiers', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + name: { + type: Sequelize.STRING(50), + allowNull: false, + }, + size: { + type: Sequelize.STRING(50), + allowNull: false, + }, + sortOrder: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0 + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' } }) - ); + ]); + + await Promise.all([ + queryInterface.addIndex('Donations', ['nonprofitId']), + queryInterface.addIndex('Donations', ['paymentTransactionId']), + queryInterface.addIndex('Donations', ['donorId']), + queryInterface.addIndex('Donors', ['email']), + queryInterface.addIndex('NonprofitDonationTiers', ['nonprofitId']), + queryInterface.addIndex('Nonprofits', ['isDeleted']), + queryInterface.addIndex('Nonprofits', ['status', 'legalNameSearch', 'isDeleted']), + queryInterface.addIndex('Nonprofits', ['slug']), + queryInterface.addIndex('NonprofitSlides', ['nonprofitId']), + queryInterface.addIndex('Sponsors', ['sponsorTierId']), + queryInterface.addIndex('SponsorTiers', ['name']), + ]); }, down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable('Settings').then( - queryInterface.dropTable('Contents') - );; + await Promise.all([ + queryInterface.dropTable('Contents'), + queryInterface.dropTable('Donations'), + queryInterface.dropTable('Donors'), + queryInterface.dropTable('Files'), + queryInterface.dropTable('Messages'), + queryInterface.dropTable('Metrics'), + queryInterface.dropTable('NonprofitDonationTiers'), + queryInterface.dropTable('Nonprofits'), + queryInterface.dropTable('NonprofitSlides'), + queryInterface.dropTable('PaymentTransactions'), + queryInterface.dropTable('Reports'), + queryInterface.dropTable('Settings'), + queryInterface.dropTable('Sponsors'), + queryInterface.dropTable('SponsorTiers') + ]); } }; diff --git a/packages/lambda/src/api/adminRegisterNonprofit/index.js b/packages/lambda/src/api/adminRegisterNonprofit/index.js index 78bcdeda..a1983f1a 100644 --- a/packages/lambda/src/api/adminRegisterNonprofit/index.js +++ b/packages/lambda/src/api/adminRegisterNonprofit/index.js @@ -17,11 +17,11 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/deleteContents/index.js b/packages/lambda/src/api/deleteContents/index.js index d8e4d444..e96fc421 100644 --- a/packages/lambda/src/api/deleteContents/index.js +++ b/packages/lambda/src/api/deleteContents/index.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentHelper = require('./../../helpers/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); diff --git a/packages/lambda/src/api/deleteFiles/index.js b/packages/lambda/src/api/deleteFiles/index.js index 5615c9fb..da7baa05 100644 --- a/packages/lambda/src/api/deleteFiles/index.js +++ b/packages/lambda/src/api/deleteFiles/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/deleteMetrics/index.js b/packages/lambda/src/api/deleteMetrics/index.js index 2954f32f..286dd743 100644 --- a/packages/lambda/src/api/deleteMetrics/index.js +++ b/packages/lambda/src/api/deleteMetrics/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js b/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js index 3a810b6b..51fb0634 100644 --- a/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js +++ b/packages/lambda/src/api/deleteNonprofitDonationTiers/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/deleteSetting/index.js b/packages/lambda/src/api/deleteSetting/index.js index 88a7cf84..83e71233 100644 --- a/packages/lambda/src/api/deleteSetting/index.js +++ b/packages/lambda/src/api/deleteSetting/index.js @@ -17,17 +17,25 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); +const loadModels = require('./../../models/index'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); + let allModels; request.validate().then(function () { - return repository.delete(request.urlParam('key')); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Settings.destroy({ + where: { + key: request.urlParam('key') + } + }) + }); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -36,5 +44,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); }; \ No newline at end of file diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index 8c0d8f66..17cc76eb 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -17,30 +17,30 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { - const repository = new SettingsRepository(); + const lambda = new Lambda(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; + let allModels; request.validate().then(function () { - request.get('settings', []).forEach(function (data) { - settings.push(new Setting(data)); - }); - }).then(function () { - let promise = Promise.resolve(); - settings.forEach(function (setting) { - promise = promise.then(function () { - return setting.validate(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + request.get('settings', []).forEach(function (data) { + let promise = Promise.resolve(); + promise.then(function () { + return allModels.Setting.findOne(data).then(function (setting) { + settings.push(setting); + return setting.destroy(); + }); + }); }); }); - return promise; - }).then(function () { - return repository.batchDeleteByKey(settings); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -49,5 +49,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index f05a865d..4a154a5c 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/getSetting/index.js b/packages/lambda/src/api/getSetting/index.js index 64b21309..c35be3fe 100644 --- a/packages/lambda/src/api/getSetting/index.js +++ b/packages/lambda/src/api/getSetting/index.js @@ -29,4 +29,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/getSettings/index.js b/packages/lambda/src/api/getSettings/index.js index 6edb62af..6db5ef40 100644 --- a/packages/lambda/src/api/getSettings/index.js +++ b/packages/lambda/src/api/getSettings/index.js @@ -16,25 +16,35 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const SettingsRepository = require('./../../repositories/settings'); +const Sequelize = require('sequelize'); +const loadModels = require('./../../models/index'); exports.handle = function (event, context, callback) { - const repository = new SettingsRepository(); const request = new Request(event, context); const keys = request.queryParam('keys', '').split(','); + let allModels; request.validate().then(function () { - if (keys.length) { - return repository.batchGet(keys); - } else { - return repository.getAll(); - } - }).then(function (settings) { - const results = settings.map(function (setting) { - return setting.all(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + if (keys.length) { + return allModels.Setting.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } + } + }); + } else { + return allModels.Setting.findAll(); + } }); - callback(null, results); + }).then(function (settings) { + callback(null, settings); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/patchContent/index.js b/packages/lambda/src/api/patchContent/index.js index 6a36e6ed..82f1af9b 100644 --- a/packages/lambda/src/api/patchContent/index.js +++ b/packages/lambda/src/api/patchContent/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/patchContents/index.js b/packages/lambda/src/api/patchContents/index.js index da717251..51de2d75 100644 --- a/packages/lambda/src/api/patchContents/index.js +++ b/packages/lambda/src/api/patchContents/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/patchDonation/index.js b/packages/lambda/src/api/patchDonation/index.js index 532489b0..dd8421c2 100644 --- a/packages/lambda/src/api/patchDonation/index.js +++ b/packages/lambda/src/api/patchDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchMessage/index.js b/packages/lambda/src/api/patchMessage/index.js index 25bc2d0b..bfbf54e2 100644 --- a/packages/lambda/src/api/patchMessage/index.js +++ b/packages/lambda/src/api/patchMessage/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Message = require('./../../models/message'); +const Message = require('./../../dynamo-models/message'); const MessagesRepository = require('./../../repositories/messages'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchMetrics/index.js b/packages/lambda/src/api/patchMetrics/index.js index 27d1f250..67ae8172 100644 --- a/packages/lambda/src/api/patchMetrics/index.js +++ b/packages/lambda/src/api/patchMetrics/index.js @@ -16,7 +16,7 @@ const _ = require('lodash'); const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchNonprofit/index.js b/packages/lambda/src/api/patchNonprofit/index.js index aa2220e9..5e80718d 100644 --- a/packages/lambda/src/api/patchNonprofit/index.js +++ b/packages/lambda/src/api/patchNonprofit/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitDonation/index.js b/packages/lambda/src/api/patchNonprofitDonation/index.js index 90ac4ffc..43c02cbc 100644 --- a/packages/lambda/src/api/patchNonprofitDonation/index.js +++ b/packages/lambda/src/api/patchNonprofitDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const HttpException = require('./../../exceptions/http'); const NonprofitDonationsRepository = require('./../../repositories/nonprofitDonations'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitDonationTiers/index.js b/packages/lambda/src/api/patchNonprofitDonationTiers/index.js index 40a2be5b..374bd356 100644 --- a/packages/lambda/src/api/patchNonprofitDonationTiers/index.js +++ b/packages/lambda/src/api/patchNonprofitDonationTiers/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitSlide/index.js b/packages/lambda/src/api/patchNonprofitSlide/index.js index c5cce02d..1bb09675 100644 --- a/packages/lambda/src/api/patchNonprofitSlide/index.js +++ b/packages/lambda/src/api/patchNonprofitSlide/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitSlides/index.js b/packages/lambda/src/api/patchNonprofitSlides/index.js index e89cd866..40977bd6 100644 --- a/packages/lambda/src/api/patchNonprofitSlides/index.js +++ b/packages/lambda/src/api/patchNonprofitSlides/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/patchNonprofitStatus/index.js b/packages/lambda/src/api/patchNonprofitStatus/index.js index f441109e..757525b0 100644 --- a/packages/lambda/src/api/patchNonprofitStatus/index.js +++ b/packages/lambda/src/api/patchNonprofitStatus/index.js @@ -19,7 +19,7 @@ const HttpException = require('./../../exceptions/http'); const InvalidInputException = require('./../../exceptions/invalidInput'); const InvalidStatusException = require('./../../exceptions/invalidStatus'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); diff --git a/packages/lambda/src/api/patchPaymentTransaction/index.js b/packages/lambda/src/api/patchPaymentTransaction/index.js index a476adbd..5749fe40 100644 --- a/packages/lambda/src/api/patchPaymentTransaction/index.js +++ b/packages/lambda/src/api/patchPaymentTransaction/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSetting/index.js b/packages/lambda/src/api/patchSetting/index.js index df122919..9f632055 100644 --- a/packages/lambda/src/api/patchSetting/index.js +++ b/packages/lambda/src/api/patchSetting/index.js @@ -46,4 +46,4 @@ exports.handle = function (event, context, callback) { }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index c7280138..631ba5a9 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -15,46 +15,58 @@ */ const _ = require('lodash'); +const Sequelize = require('sequelize'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; + let allModels; request.validate().then(function () { const keys = request.get('settings', []).map(function (setting) { return setting.key; }); - return repository.batchGet(keys).then(function (models) { - request.get('settings', []).forEach(function (data) { - let model = _.find(models, {key: data.key}); - if (model) { - model.populate(data); - } else { - model = new Setting(data); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } } - - settings.push(model); }); }); - }).then(function () { + }).then(function (models) { + request.get('settings', []).forEach(function (data) { + let model = _.find(models, {key: data.key}); + if (model instanceof allModels.Setting) { + model.set('value', data.value); + settings.push(model); + } else { + settings.push(new allModels.Setting(data)); + } + }); + + return settings; + }).then(function (settings) { let promise = Promise.resolve(); settings.forEach(function (setting) { - promise = promise.then(function () { - return setting.validate(); - }); + if (setting instanceof allModels.Setting) { + promise = promise.then(function () { + return allModels.Setting.upsert(setting.toJSON()); + }); + } }); + return promise; - }).then(function () { - return repository.batchUpdate(settings); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -63,5 +75,7 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/patchSponsor/index.js b/packages/lambda/src/api/patchSponsor/index.js index 8df74646..00aba9f8 100644 --- a/packages/lambda/src/api/patchSponsor/index.js +++ b/packages/lambda/src/api/patchSponsor/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsorTier/index.js b/packages/lambda/src/api/patchSponsorTier/index.js index af68c281..6fdef97a 100644 --- a/packages/lambda/src/api/patchSponsorTier/index.js +++ b/packages/lambda/src/api/patchSponsorTier/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsorTiers/index.js b/packages/lambda/src/api/patchSponsorTiers/index.js index bfe51d1c..b8be51b5 100644 --- a/packages/lambda/src/api/patchSponsorTiers/index.js +++ b/packages/lambda/src/api/patchSponsorTiers/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchSponsors/index.js b/packages/lambda/src/api/patchSponsors/index.js index bdd46761..3d4da37d 100644 --- a/packages/lambda/src/api/patchSponsors/index.js +++ b/packages/lambda/src/api/patchSponsors/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/patchUser/index.js b/packages/lambda/src/api/patchUser/index.js index acc89c7e..c5f15d65 100644 --- a/packages/lambda/src/api/patchUser/index.js +++ b/packages/lambda/src/api/patchUser/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserResourceMiddleware = require('./../../middleware/userResource'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/postContent/index.js b/packages/lambda/src/api/postContent/index.js index 0c5a87eb..38b0f8de 100644 --- a/packages/lambda/src/api/postContent/index.js +++ b/packages/lambda/src/api/postContent/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../../models/content'); +const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postDonation/index.js b/packages/lambda/src/api/postDonation/index.js index 98d2939f..747ec136 100644 --- a/packages/lambda/src/api/postDonation/index.js +++ b/packages/lambda/src/api/postDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postDonor/index.js b/packages/lambda/src/api/postDonor/index.js index f322c26d..483ff6fa 100644 --- a/packages/lambda/src/api/postDonor/index.js +++ b/packages/lambda/src/api/postDonor/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postFile/index.js b/packages/lambda/src/api/postFile/index.js index df8e0c5d..bf4656d5 100644 --- a/packages/lambda/src/api/postFile/index.js +++ b/packages/lambda/src/api/postFile/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postMessage/index.js b/packages/lambda/src/api/postMessage/index.js index 50b99771..4e52477f 100644 --- a/packages/lambda/src/api/postMessage/index.js +++ b/packages/lambda/src/api/postMessage/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Message = require('./../../models/message'); +const Message = require('./../../dynamo-models/message'); const MessagesRepository = require('./../../repositories/messages'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofit/index.js b/packages/lambda/src/api/postNonprofit/index.js index 3b8e2940..7742b24d 100644 --- a/packages/lambda/src/api/postNonprofit/index.js +++ b/packages/lambda/src/api/postNonprofit/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postNonprofitDonation/index.js b/packages/lambda/src/api/postNonprofitDonation/index.js index 2f0ff4bc..7a138fd3 100644 --- a/packages/lambda/src/api/postNonprofitDonation/index.js +++ b/packages/lambda/src/api/postNonprofitDonation/index.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/api/postNonprofitDonationTier/index.js b/packages/lambda/src/api/postNonprofitDonationTier/index.js index 807df889..ec441bc9 100644 --- a/packages/lambda/src/api/postNonprofitDonationTier/index.js +++ b/packages/lambda/src/api/postNonprofitDonationTier/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const NonprofitDonationTier = require('./../../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('./../../dynamo-models/nonprofitDonationTier'); const NonprofitDonationTiersRepository = require('./../../repositories/nonprofitDonationTiers'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitReport/index.js b/packages/lambda/src/api/postNonprofitReport/index.js index ccff3a21..39fee218 100644 --- a/packages/lambda/src/api/postNonprofitReport/index.js +++ b/packages/lambda/src/api/postNonprofitReport/index.js @@ -18,7 +18,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitReportsRepository = require('./../../repositories/nonprofitReports'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitSlide/index.js b/packages/lambda/src/api/postNonprofitSlide/index.js index faecf3c7..ac861c2f 100644 --- a/packages/lambda/src/api/postNonprofitSlide/index.js +++ b/packages/lambda/src/api/postNonprofitSlide/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); -const NonprofitSlide = require('./../../models/nonprofitSlide'); +const NonprofitSlide = require('./../../dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('./../../repositories/nonprofitSlides'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postNonprofitUser/index.js b/packages/lambda/src/api/postNonprofitUser/index.js index 4d00788c..2fde0036 100644 --- a/packages/lambda/src/api/postNonprofitUser/index.js +++ b/packages/lambda/src/api/postNonprofitUser/index.js @@ -19,7 +19,7 @@ const HttpException = require('./../../exceptions/http'); const NonprofitResourceMiddleware = require('./../../middleware/nonprofitResource'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/api/postPaymentTransaction/index.js b/packages/lambda/src/api/postPaymentTransaction/index.js index be0bdc05..c5f4624e 100644 --- a/packages/lambda/src/api/postPaymentTransaction/index.js +++ b/packages/lambda/src/api/postPaymentTransaction/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postReport/index.js b/packages/lambda/src/api/postReport/index.js index b13b31b7..74aeb990 100644 --- a/packages/lambda/src/api/postReport/index.js +++ b/packages/lambda/src/api/postReport/index.js @@ -16,7 +16,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const ReportsRepository = require('./../../repositories/reports'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index 25b68363..d40b900f 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -18,37 +18,43 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const ResourceAlreadyExistsException = require('./../../exceptions/resourceAlreadyExists'); -const Setting = require('./../../models/setting'); -const SettingsRepository = require('./../../repositories/settings'); +const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); - const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let setting = new Setting(request._body); + let setting; + let allModels; request.validate().then(function () { return new Promise(function (resolve, reject) { - repository.get(request.get('key')).then(function () { - reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); - }).catch(function () { - resolve(); + loadModels().then(function (models) { + allModels = models; + setting = new allModels.Setting(request._body); + }).then(function () { + return allModels.Setting.findOne({key: request.get('key')}); + }).then(function (setting) { + if (setting instanceof allModels.Setting) { + reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); + } else { + resolve(); + } }); }); }).then(function () { - return setting.validate(); - }).then(function () { - return repository.save(setting); + return allModels.Setting.create(setting.toJSON()); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { return DynamicContentHelper.regenerateDynamicContent([setting.key], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); }).then(function () { - callback(null, setting.all()); + callback(null, setting); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }).finally(function () { + return allModels.sequelize.close(); }); -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/api/postSponsor/index.js b/packages/lambda/src/api/postSponsor/index.js index c233c420..35541b53 100644 --- a/packages/lambda/src/api/postSponsor/index.js +++ b/packages/lambda/src/api/postSponsor/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../models/sponsor'); +const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postSponsorTier/index.js b/packages/lambda/src/api/postSponsorTier/index.js index 0c00f1bd..af716e2f 100644 --- a/packages/lambda/src/api/postSponsorTier/index.js +++ b/packages/lambda/src/api/postSponsorTier/index.js @@ -17,7 +17,7 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../models/sponsorTier'); +const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postUser/index.js b/packages/lambda/src/api/postUser/index.js index d140c288..ae8ba2bb 100644 --- a/packages/lambda/src/api/postUser/index.js +++ b/packages/lambda/src/api/postUser/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/api/processDonations/index.js b/packages/lambda/src/api/processDonations/index.js index c5c7892c..69c19748 100644 --- a/packages/lambda/src/api/processDonations/index.js +++ b/packages/lambda/src/api/processDonations/index.js @@ -16,15 +16,15 @@ const _ = require('lodash'); const axios = require('axios'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const DonationsRepository = require('./../../repositories/donations'); -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const NonprofitsRepository = require('./../../repositories/nonprofits'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const Request = require('./../../aws/request'); const SettingHelper = require('./../../helpers/setting'); diff --git a/packages/lambda/src/api/registerNonprofit/index.js b/packages/lambda/src/api/registerNonprofit/index.js index 9eb8d403..c4e52ed2 100644 --- a/packages/lambda/src/api/registerNonprofit/index.js +++ b/packages/lambda/src/api/registerNonprofit/index.js @@ -16,11 +16,11 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); -const Nonprofit = require('./../../models/nonprofit'); +const Nonprofit = require('./../../dynamo-models/nonprofit'); const NonprofitHelper = require('./../../helpers/nonprofit'); const NonprofitsRepository = require('./../../repositories/nonprofits'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/api/resendUserEmailVerification/index.js b/packages/lambda/src/api/resendUserEmailVerification/index.js index 8303d26f..9eae74cd 100644 --- a/packages/lambda/src/api/resendUserEmailVerification/index.js +++ b/packages/lambda/src/api/resendUserEmailVerification/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); diff --git a/packages/lambda/src/aws/cloudformation.js b/packages/lambda/src/aws/cloudformation.js new file mode 100644 index 00000000..3b7ac0c8 --- /dev/null +++ b/packages/lambda/src/aws/cloudformation.js @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const AWS = require('aws-sdk'); + +/** + * CloudFormation constructor + * + * @constructor + */ +function CloudFormation() { +} + +/** + * Get an output from a cloud formation stack + * + * @param region + * @param stackName + * @returns {Promise} + */ +CloudFormation.prototype.describeStacks = (region, stackName) => { + const cloudFormation = new AWS.CloudFormation({region: region}); + return cloudFormation.describeStacks({StackName: stackName}).promise(); +}; + +module.exports = CloudFormation; diff --git a/packages/lambda/src/custom/cognitoCreateUser/index.js b/packages/lambda/src/custom/cognitoCreateUser/index.js index 3a1189ed..694e572a 100644 --- a/packages/lambda/src/custom/cognitoCreateUser/index.js +++ b/packages/lambda/src/custom/cognitoCreateUser/index.js @@ -17,7 +17,7 @@ const Cognito = require('./../../aws/cognito'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const User = require('./../../models/user'); +const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { diff --git a/packages/lambda/src/custom/generateDonationsReceipt/index.js b/packages/lambda/src/custom/generateDonationsReceipt/index.js index 3b2e1ea8..afa4e300 100644 --- a/packages/lambda/src/custom/generateDonationsReceipt/index.js +++ b/packages/lambda/src/custom/generateDonationsReceipt/index.js @@ -15,13 +15,13 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationsRepository = require('./../../repositories/donations'); -const Donor = require('./../../models/donor'); +const Donor = require('./../../dynamo-models/donor'); const DonorsRepository = require('./../../repositories/donors'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); -const PaymentTransaction = require('./../../models/paymentTransaction'); +const PaymentTransaction = require('./../../dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('./../../repositories/paymentTransactions'); const QueryBuilder = require('./../../aws/queryBuilder'); const RenderHelper = require('./../../helpers/render'); diff --git a/packages/lambda/src/custom/generateReport/index.js b/packages/lambda/src/custom/generateReport/index.js index d09a6929..0be30728 100644 --- a/packages/lambda/src/custom/generateReport/index.js +++ b/packages/lambda/src/custom/generateReport/index.js @@ -15,15 +15,15 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const DonationHelper = require('./../../helpers/donation'); const DonationsRepository = require('./../../repositories/donations'); -const File = require('./../../models/file'); +const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const json2csv = require('json2csv'); const NonprofitDonationsRepository = require('./../../repositories/nonprofitDonations'); const QueryBuilder = require('./../../aws/queryBuilder'); -const Report = require('./../../models/report'); +const Report = require('./../../dynamo-models/report'); const ReportHelper = require('./../../helpers/report'); const ReportsRepository = require('./../../repositories/reports'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/metricAddAmount/index.js b/packages/lambda/src/custom/metricAddAmount/index.js index 5e6023e5..8ebc1dc0 100644 --- a/packages/lambda/src/custom/metricAddAmount/index.js +++ b/packages/lambda/src/custom/metricAddAmount/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/metricMaxAmount/index.js b/packages/lambda/src/custom/metricMaxAmount/index.js index 6526e55d..aa876d7c 100644 --- a/packages/lambda/src/custom/metricMaxAmount/index.js +++ b/packages/lambda/src/custom/metricMaxAmount/index.js @@ -15,7 +15,7 @@ */ const HttpException = require('./../../exceptions/http'); -const Metric = require('./../../models/metric'); +const Metric = require('./../../dynamo-models/metric'); const MetricsRepository = require('./../../repositories/metrics'); const Request = require('./../../aws/request'); diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index d00c6d78..cc0b9c94 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -17,7 +17,7 @@ const _ = require('lodash'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const Setting = require('./../../models/setting'); +const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const S3 = require('./../../aws/s3'); @@ -94,4 +94,4 @@ const getSettingValue = function (key, value) { }); return promise; -}; \ No newline at end of file +}; diff --git a/packages/lambda/src/custom/sendDonationNotificationEmail/index.js b/packages/lambda/src/custom/sendDonationNotificationEmail/index.js index 8db2a997..983eacb8 100644 --- a/packages/lambda/src/custom/sendDonationNotificationEmail/index.js +++ b/packages/lambda/src/custom/sendDonationNotificationEmail/index.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Donation = require('./../../models/donation'); +const Donation = require('./../../dynamo-models/donation'); const EmailHelper = require('./../../helpers/email'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js index 98e9eda9..47c6e47e 100644 --- a/packages/lambda/src/database/bootstrapDatabase/index.js +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -32,12 +32,12 @@ exports.handle = function (event, context, callback) { return; } + let sequelize; request.validate().then(function () { return Promise.all([ secretsManager.getSecretValue(process.env.AWS_REGION, process.env.ADMIN_DATABASE_SECRET_ID), secretsManager.getSecretValue(process.env.AWS_REGION, process.env.MAINTENANCE_DATABASE_SECRET_ID), - secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID), - secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READONLY_DATABASE_SECRET_ID) + secretsManager.getSecretValue(process.env.AWS_REGION, process.env.READWRITE_DATABASE_SECRET_ID) ]); }).then(function (secrets) { const dbHost = process.env.DATABASE_HOST; @@ -45,15 +45,14 @@ exports.handle = function (event, context, callback) { const adminSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.ADMIN_DATABASE_SECRET_ID).SecretString); const maintenanceSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.MAINTENANCE_DATABASE_SECRET_ID).SecretString); const readwriteSecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READWRITE_DATABASE_SECRET_ID).SecretString); - const readonlySecret = JSON.parse(secrets.find(it => it['Name'] === process.env.READONLY_DATABASE_SECRET_ID).SecretString); - const sequelize = new Sequelize({ - host: dbHost, + sequelize = new Sequelize({ + host: adminSecret.host, username: adminSecret.username, password: adminSecret.password, + port: adminSecret.port, dialect: 'mysql', dialectModule: mysql2, - port: 3306, logging: false, // don't log the sql so we don't log the passwords ssl: true, dialectOptions: { @@ -68,9 +67,7 @@ exports.handle = function (event, context, callback) { 'CREATE USER IF NOT EXISTS "' + maintenanceSecret.username + '"@"%" IDENTIFIED BY "' + maintenanceSecret.password + '"; ' + 'GRANT ALL PRIVILEGES ON `' + dbName+ '`.* TO "' + maintenanceSecret.username + '"@"%"; ' + 'CREATE USER IF NOT EXISTS "' + readwriteSecret.username + '"@"%" IDENTIFIED BY "' + readwriteSecret.password + '"; ' + - 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%"; ' + - 'CREATE USER IF NOT EXISTS "' + readonlySecret.username + '"@"%" IDENTIFIED BY "' + readonlySecret.password + '"; ' + - 'GRANT SELECT ON `' + dbName+ '`.* TO "' + readonlySecret.username + '"@"%";' + 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, EXECUTE ON `' + dbName+ '`.* TO "' + readwriteSecret.username + '"@"%";' ); }).then(function () { response.send(event, context, response.SUCCESS); @@ -79,5 +76,9 @@ exports.handle = function (event, context, callback) { logger.log(err); response.send(event, context, response.FAILED); callback(err); + }).finally(function() { + if (sequelize) { + sequelize.close(); + } }); }; diff --git a/packages/lambda/src/models/content.js b/packages/lambda/src/dynamo-models/content.js similarity index 100% rename from packages/lambda/src/models/content.js rename to packages/lambda/src/dynamo-models/content.js diff --git a/packages/lambda/src/models/donation.js b/packages/lambda/src/dynamo-models/donation.js similarity index 100% rename from packages/lambda/src/models/donation.js rename to packages/lambda/src/dynamo-models/donation.js diff --git a/packages/lambda/src/models/donor.js b/packages/lambda/src/dynamo-models/donor.js similarity index 100% rename from packages/lambda/src/models/donor.js rename to packages/lambda/src/dynamo-models/donor.js diff --git a/packages/lambda/src/models/file.js b/packages/lambda/src/dynamo-models/file.js similarity index 100% rename from packages/lambda/src/models/file.js rename to packages/lambda/src/dynamo-models/file.js diff --git a/packages/lambda/src/models/message.js b/packages/lambda/src/dynamo-models/message.js similarity index 100% rename from packages/lambda/src/models/message.js rename to packages/lambda/src/dynamo-models/message.js diff --git a/packages/lambda/src/models/metric.js b/packages/lambda/src/dynamo-models/metric.js similarity index 100% rename from packages/lambda/src/models/metric.js rename to packages/lambda/src/dynamo-models/metric.js diff --git a/packages/lambda/src/models/model.js b/packages/lambda/src/dynamo-models/model.js similarity index 100% rename from packages/lambda/src/models/model.js rename to packages/lambda/src/dynamo-models/model.js diff --git a/packages/lambda/src/models/nonprofit.js b/packages/lambda/src/dynamo-models/nonprofit.js similarity index 100% rename from packages/lambda/src/models/nonprofit.js rename to packages/lambda/src/dynamo-models/nonprofit.js diff --git a/packages/lambda/src/models/nonprofitDonationTier.js b/packages/lambda/src/dynamo-models/nonprofitDonationTier.js similarity index 100% rename from packages/lambda/src/models/nonprofitDonationTier.js rename to packages/lambda/src/dynamo-models/nonprofitDonationTier.js diff --git a/packages/lambda/src/models/nonprofitSlide.js b/packages/lambda/src/dynamo-models/nonprofitSlide.js similarity index 100% rename from packages/lambda/src/models/nonprofitSlide.js rename to packages/lambda/src/dynamo-models/nonprofitSlide.js diff --git a/packages/lambda/src/models/paymentTransaction.js b/packages/lambda/src/dynamo-models/paymentTransaction.js similarity index 100% rename from packages/lambda/src/models/paymentTransaction.js rename to packages/lambda/src/dynamo-models/paymentTransaction.js diff --git a/packages/lambda/src/models/report.js b/packages/lambda/src/dynamo-models/report.js similarity index 100% rename from packages/lambda/src/models/report.js rename to packages/lambda/src/dynamo-models/report.js diff --git a/packages/lambda/src/models/sponsor.js b/packages/lambda/src/dynamo-models/sponsor.js similarity index 100% rename from packages/lambda/src/models/sponsor.js rename to packages/lambda/src/dynamo-models/sponsor.js diff --git a/packages/lambda/src/models/sponsorTier.js b/packages/lambda/src/dynamo-models/sponsorTier.js similarity index 100% rename from packages/lambda/src/models/sponsorTier.js rename to packages/lambda/src/dynamo-models/sponsorTier.js diff --git a/packages/lambda/src/models/user.js b/packages/lambda/src/dynamo-models/user.js similarity index 100% rename from packages/lambda/src/models/user.js rename to packages/lambda/src/dynamo-models/user.js diff --git a/packages/lambda/src/helpers/generator.js b/packages/lambda/src/helpers/generator.js index 818d076d..a960ea67 100644 --- a/packages/lambda/src/helpers/generator.js +++ b/packages/lambda/src/helpers/generator.js @@ -384,7 +384,7 @@ Generator.prototype.data = function (type, data) { */ Generator.prototype.model = function (type, data) { this._validateType(type); - const Model = require(`./../models/${type}`); + const Model = require(`./../dynamo-models/${type}`); return new Model(this.data(type, data)); }; diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js new file mode 100644 index 00000000..e7b951e7 --- /dev/null +++ b/packages/lambda/src/models/connect.js @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const CloudFormation = require('../aws/cloudformation'); +const SecretsManager = require('../aws/secretsManager'); +const mysql2 = require('mysql2'); +const Sequelize = require('sequelize'); + +module.exports = function() { + const cloudFormation = new CloudFormation(); + return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { + const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadwriteSecret').OutputValue; + const secretsManager = new SecretsManager(); + return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); + }).then(function (secret) { + const readwriteSecret = JSON.parse(secret.SecretString); + return new Sequelize({ + host: readwriteSecret.host, + username: readwriteSecret.username, + password: readwriteSecret.password, + database: readwriteSecret.database, + port: readwriteSecret.port, + dialect: 'mysql', + dialectModule: mysql2, + ssl: true, + dialectOptions: { + ssl: 'Amazon RDS', + connectTimeout: 60000 + } + }); + }).then(function (sequelize) { + return sequelize; + }); +}; diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js new file mode 100644 index 00000000..c51ac3ba --- /dev/null +++ b/packages/lambda/src/models/index.js @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const connect = require('./connect.js'); + +module.exports = function() { + return connect().then(function(sequelize) { + const models = {"sequelize": sequelize}; + const model = require('./setting')(sequelize); + models[model.name] = model; + return models; + }); +} diff --git a/packages/lambda/src/models/setting.js b/packages/lambda/src/models/setting.js index 0486df1e..f518a9d5 100644 --- a/packages/lambda/src/models/setting.js +++ b/packages/lambda/src/models/setting.js @@ -14,48 +14,21 @@ * limitations under the License. */ -const Model = require('./model'); +'use strict'; -/** - * Setting constructor - * - * @param {{}} [data] - * @constructor - */ -function Setting(data) { - Model.call(this, data); -} - -/** - * Extend the base Model - * - * @type {Model} - */ -Setting.prototype = new Model(); +const { DataTypes } = require('sequelize'); -/** - * The allowed attributes for this model - * - * @type {[*]} - */ -Setting.prototype.attributes = [ - 'key', - 'value' -]; - -/** - * Validation constraints for this model - * - * @type {{}} - */ -Setting.prototype.constraints = { - key: { - presence: true, - type: 'string', - }, - value: { - presence: false, - }, +module.exports = (sequelize) => { + return sequelize.define('Setting', { + key: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true + } + }, + value: { + type: DataTypes.STRING, + } + }); }; - -module.exports = Setting; \ No newline at end of file diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index 29161f4b..0493109f 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Content = require('./../models/content'); +const Content = require('./../dynamo-models/content'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/donations.js b/packages/lambda/src/repositories/donations.js index 5baf8ab2..09df6aa8 100644 --- a/packages/lambda/src/repositories/donations.js +++ b/packages/lambda/src/repositories/donations.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../models/donation'); +const Donation = require('./../dynamo-models/donation'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/donors.js b/packages/lambda/src/repositories/donors.js index eecc2162..cfb72a34 100644 --- a/packages/lambda/src/repositories/donors.js +++ b/packages/lambda/src/repositories/donors.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donor = require('./../models/donor'); +const Donor = require('./../dynamo-models/donor'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); diff --git a/packages/lambda/src/repositories/files.js b/packages/lambda/src/repositories/files.js index 743f2d42..72eff845 100644 --- a/packages/lambda/src/repositories/files.js +++ b/packages/lambda/src/repositories/files.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const File = require('./../models/file'); +const File = require('./../dynamo-models/file'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/messages.js b/packages/lambda/src/repositories/messages.js index 9ef994aa..b2ec7353 100644 --- a/packages/lambda/src/repositories/messages.js +++ b/packages/lambda/src/repositories/messages.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Message = require('./../models/message'); +const Message = require('./../dynamo-models/message'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/metrics.js b/packages/lambda/src/repositories/metrics.js index 442e2517..1429a66f 100644 --- a/packages/lambda/src/repositories/metrics.js +++ b/packages/lambda/src/repositories/metrics.js @@ -16,7 +16,7 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); -const Metric = require('./../models/metric'); +const Metric = require('./../dynamo-models/metric'); /** * MetricsRepository constructor diff --git a/packages/lambda/src/repositories/nonprofitDonationTiers.js b/packages/lambda/src/repositories/nonprofitDonationTiers.js index 8356ec59..0db38a25 100644 --- a/packages/lambda/src/repositories/nonprofitDonationTiers.js +++ b/packages/lambda/src/repositories/nonprofitDonationTiers.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const NonprofitDonationTier = require('../models/nonprofitDonationTier'); +const NonprofitDonationTier = require('../dynamo-models/nonprofitDonationTier'); const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); diff --git a/packages/lambda/src/repositories/nonprofitDonations.js b/packages/lambda/src/repositories/nonprofitDonations.js index bbdb74fd..83aced1f 100644 --- a/packages/lambda/src/repositories/nonprofitDonations.js +++ b/packages/lambda/src/repositories/nonprofitDonations.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Donation = require('./../models/donation'); +const Donation = require('./../dynamo-models/donation'); const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); diff --git a/packages/lambda/src/repositories/nonprofitReports.js b/packages/lambda/src/repositories/nonprofitReports.js index 1ec9383a..e2c38262 100644 --- a/packages/lambda/src/repositories/nonprofitReports.js +++ b/packages/lambda/src/repositories/nonprofitReports.js @@ -16,7 +16,7 @@ const NonprofitRepository = require('./nonprofits'); const QueryBuilder = require('./../aws/queryBuilder'); -const Report = require('./../models/report'); +const Report = require('./../dynamo-models/report'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/nonprofitSlides.js b/packages/lambda/src/repositories/nonprofitSlides.js index 7e5844bc..41a410c2 100644 --- a/packages/lambda/src/repositories/nonprofitSlides.js +++ b/packages/lambda/src/repositories/nonprofitSlides.js @@ -15,7 +15,7 @@ */ const NonprofitRepository = require('./nonprofits'); -const NonprofitSlide = require('../models/nonprofitSlide'); +const NonprofitSlide = require('../dynamo-models/nonprofitSlide'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); diff --git a/packages/lambda/src/repositories/nonprofitUsers.js b/packages/lambda/src/repositories/nonprofitUsers.js index 6a0c50a7..649c602e 100644 --- a/packages/lambda/src/repositories/nonprofitUsers.js +++ b/packages/lambda/src/repositories/nonprofitUsers.js @@ -19,7 +19,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const User = require('./../models/user'); +const User = require('./../dynamo-models/user'); /** * NonprofitUsersRepository constructor diff --git a/packages/lambda/src/repositories/nonprofits.js b/packages/lambda/src/repositories/nonprofits.js index f470bb3b..af307afc 100644 --- a/packages/lambda/src/repositories/nonprofits.js +++ b/packages/lambda/src/repositories/nonprofits.js @@ -15,7 +15,7 @@ */ const _ = require('lodash'); -const Nonprofit = require('./../models/nonprofit'); +const Nonprofit = require('./../dynamo-models/nonprofit'); const NonprofitHelper = require('./../helpers/nonprofit'); const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./../repositories/repository'); diff --git a/packages/lambda/src/repositories/paymentTransactions.js b/packages/lambda/src/repositories/paymentTransactions.js index 5178138d..ff49b1aa 100644 --- a/packages/lambda/src/repositories/paymentTransactions.js +++ b/packages/lambda/src/repositories/paymentTransactions.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const PaymentTransaction = require('./../models/paymentTransaction'); +const PaymentTransaction = require('./../dynamo-models/paymentTransaction'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/reports.js b/packages/lambda/src/repositories/reports.js index 498aff48..e90c2b9e 100644 --- a/packages/lambda/src/repositories/reports.js +++ b/packages/lambda/src/repositories/reports.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const Report = require('./../models/report'); +const Report = require('./../dynamo-models/report'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index fff0c81d..4fe06c08 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -16,7 +16,7 @@ const _ = require('lodash'); const AWS = require('aws-sdk'); -const Model = require('./../models/model'); +const Model = require('./../dynamo-models/model'); const QueryBuilder = require('./../aws/queryBuilder'); /** diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 95e3fec3..9b323931 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -17,7 +17,7 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Setting = require('./../models/setting'); +const Setting = require('../models/index').Setting; /** * SettingsRepository constructor @@ -46,17 +46,7 @@ SettingsRepository.prototype = new Repository(); * @return {Promise} */ SettingsRepository.prototype.get = function (key) { - const repository = this; - return new Promise(function (resolve, reject) { - repository.getByKey('key', key).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new Setting(data.Item)); - } - reject(new ResourceNotFoundException('The specified setting does not exist.')); - }).catch(function (err) { - reject(err); - }); - }); + return Setting.findOne({ where: {key: key}}); }; /** @@ -65,20 +55,7 @@ SettingsRepository.prototype.get = function (key) { * @return {Promise} */ SettingsRepository.prototype.getAll = function () { - const repository = this; - return new Promise(function (resolve, reject) { - repository.batchScan().then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Setting(item)); - }); - } - resolve(results); - }).catch(function (err) { - reject(err); - }); - }); + return Setting.findAll(); }; /** @@ -180,4 +157,4 @@ SettingsRepository.prototype.save = function (model) { }); }; -module.exports = SettingsRepository; \ No newline at end of file +module.exports = SettingsRepository; diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index ef6a1d8c..8931e79d 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -18,7 +18,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const SponsorTier = require('./../models/sponsorTier'); +const SponsorTier = require('./../dynamo-models/sponsorTier'); /** * SponsorTiersRepository constructor diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 3739e01c..697f5b56 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -18,7 +18,7 @@ const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Sponsor = require('./../models/sponsor'); +const Sponsor = require('./../dynamo-models/sponsor'); const SponsorTiersRepository = require('./sponsorTiers'); /** diff --git a/packages/lambda/src/repositories/users.js b/packages/lambda/src/repositories/users.js index 2beaaa05..26055a8e 100644 --- a/packages/lambda/src/repositories/users.js +++ b/packages/lambda/src/repositories/users.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const User = require('./../models/user'); +const User = require('./../dynamo-models/user'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); diff --git a/packages/lambda/test/models/donation.js b/packages/lambda/test/models/donation.js index 55c72e87..6e5bc697 100644 --- a/packages/lambda/test/models/donation.js +++ b/packages/lambda/test/models/donation.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Donation = require('../../src/models/donation'); -const Model = require('../../src/models/model'); +const Donation = require('../../src/dynamo-models/donation'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Donation', function () { diff --git a/packages/lambda/test/models/donor.js b/packages/lambda/test/models/donor.js index 80c19a8c..991f3ec4 100644 --- a/packages/lambda/test/models/donor.js +++ b/packages/lambda/test/models/donor.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Donor = require('../../src/models/donor'); -const Model = require('../../src/models/model'); +const Donor = require('../../src/dynamo-models/donor'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Donor', function () { diff --git a/packages/lambda/test/models/file.js b/packages/lambda/test/models/file.js index 6f5680f3..790b3b72 100644 --- a/packages/lambda/test/models/file.js +++ b/packages/lambda/test/models/file.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const File = require('../../src/models/file'); -const Model = require('../../src/models/model'); +const File = require('../../src/dynamo-models/file'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('File', function () { diff --git a/packages/lambda/test/models/message.js b/packages/lambda/test/models/message.js index 1fc653d7..3421b558 100644 --- a/packages/lambda/test/models/message.js +++ b/packages/lambda/test/models/message.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Message = require('../../src/models/message'); -const Model = require('../../src/models/model'); +const Message = require('../../src/dynamo-models/message'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Message', function () { diff --git a/packages/lambda/test/models/metric.js b/packages/lambda/test/models/metric.js index e82fa59c..90e9058e 100644 --- a/packages/lambda/test/models/metric.js +++ b/packages/lambda/test/models/metric.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Metric = require('../../src/models/metric'); -const Model = require('../../src/models/model'); +const Metric = require('../../src/dynamo-models/metric'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Metric', function () { diff --git a/packages/lambda/test/models/model.js b/packages/lambda/test/models/model.js index a1a2a568..41dc51bb 100644 --- a/packages/lambda/test/models/model.js +++ b/packages/lambda/test/models/model.js @@ -15,7 +15,7 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('Model', function () { diff --git a/packages/lambda/test/models/nonprofit.js b/packages/lambda/test/models/nonprofit.js index aef7dcde..3c1fd296 100644 --- a/packages/lambda/test/models/nonprofit.js +++ b/packages/lambda/test/models/nonprofit.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Nonprofit = require('../../src/models/nonprofit'); +const Model = require('../../src/dynamo-models/model'); +const Nonprofit = require('../../src/dynamo-models/nonprofit'); const NonprofitHelper = require('../../src/helpers/nonprofit'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/nonprofitSlide.js b/packages/lambda/test/models/nonprofitSlide.js index e2e3a625..eb7c3e38 100644 --- a/packages/lambda/test/models/nonprofitSlide.js +++ b/packages/lambda/test/models/nonprofitSlide.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const NonprofitSlide = require('../../src/models/nonprofitSlide'); +const Model = require('../../src/dynamo-models/model'); +const NonprofitSlide = require('../../src/dynamo-models/nonprofitSlide'); const NonprofitSlideHelper = require('../../src/helpers/nonprofitSlide'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/paymentTransaction.js b/packages/lambda/test/models/paymentTransaction.js index a4ec101c..d9e0f90e 100644 --- a/packages/lambda/test/models/paymentTransaction.js +++ b/packages/lambda/test/models/paymentTransaction.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const PaymentTransaction = require('../../src/models/paymentTransaction'); -const Model = require('../../src/models/model'); +const PaymentTransaction = require('../../src/dynamo-models/paymentTransaction'); +const Model = require('../../src/dynamo-models/model'); const TestHelper = require('../helpers/test'); describe('PaymentTransaction', function () { diff --git a/packages/lambda/test/models/report.js b/packages/lambda/test/models/report.js index caf11755..e05de769 100644 --- a/packages/lambda/test/models/report.js +++ b/packages/lambda/test/models/report.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Report = require('../../src/models/report'); +const Model = require('../../src/dynamo-models/model'); +const Report = require('../../src/dynamo-models/report'); const ReportHelper = require('../../src/helpers/report'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/models/setting.js b/packages/lambda/test/models/setting.js index 9519fc56..7ceca542 100644 --- a/packages/lambda/test/models/setting.js +++ b/packages/lambda/test/models/setting.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Setting = require('../../src/models/setting'); +const Model = require('../../src/dynamo-models/model'); +const Setting = require('../../src/dynamo-models/setting'); const TestHelper = require('../helpers/test'); describe('Setting', function () { diff --git a/packages/lambda/test/models/sponsor.js b/packages/lambda/test/models/sponsor.js index 9f761f43..2a1a4fb0 100644 --- a/packages/lambda/test/models/sponsor.js +++ b/packages/lambda/test/models/sponsor.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const Sponsor = require('../../src/models/sponsor'); +const Model = require('../../src/dynamo-models/model'); +const Sponsor = require('../../src/dynamo-models/sponsor'); const TestHelper = require('../helpers/test'); describe('Sponsor', function () { diff --git a/packages/lambda/test/models/sponsorTier.js b/packages/lambda/test/models/sponsorTier.js index bc1d8fb1..148e64eb 100644 --- a/packages/lambda/test/models/sponsorTier.js +++ b/packages/lambda/test/models/sponsorTier.js @@ -15,9 +15,9 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); +const Model = require('../../src/dynamo-models/model'); const SponsorHelper = require('../../src/helpers/sponsor'); -const SponsorTier = require('../../src/models/sponsorTier'); +const SponsorTier = require('../../src/dynamo-models/sponsorTier'); const TestHelper = require('../helpers/test'); describe('SponsorTier', function () { diff --git a/packages/lambda/test/models/user.js b/packages/lambda/test/models/user.js index cd969a15..c7364283 100644 --- a/packages/lambda/test/models/user.js +++ b/packages/lambda/test/models/user.js @@ -15,8 +15,8 @@ */ const assert = require('assert'); -const Model = require('../../src/models/model'); -const User = require('../../src/models/user'); +const Model = require('../../src/dynamo-models/model'); +const User = require('../../src/dynamo-models/user'); const TestHelper = require('../helpers/test'); describe('User', function () { diff --git a/packages/lambda/test/repositories/donations.js b/packages/lambda/test/repositories/donations.js index f64c9134..5a8c3301 100644 --- a/packages/lambda/test/repositories/donations.js +++ b/packages/lambda/test/repositories/donations.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Donation = require('../../src/models/donation'); +const Donation = require('../../src/dynamo-models/donation'); const DonationsRepository = require('../../src/repositories/donations'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/donors.js b/packages/lambda/test/repositories/donors.js index dcd7219c..67f25d62 100644 --- a/packages/lambda/test/repositories/donors.js +++ b/packages/lambda/test/repositories/donors.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Donor = require('../../src/models/donor'); +const Donor = require('../../src/dynamo-models/donor'); const DonorsRepository = require('../../src/repositories/donors'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/messages.js b/packages/lambda/test/repositories/messages.js index bac7f7fb..40f15b68 100644 --- a/packages/lambda/test/repositories/messages.js +++ b/packages/lambda/test/repositories/messages.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Message = require('../../src/models/message'); +const Message = require('../../src/dynamo-models/message'); const MessagesRepository = require('../../src/repositories/messages'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/metrics.js b/packages/lambda/test/repositories/metrics.js index dac1ce33..5b00a07a 100644 --- a/packages/lambda/test/repositories/metrics.js +++ b/packages/lambda/test/repositories/metrics.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Metric = require('./../../src/models/metric'); +const Metric = require('./../../src/dynamo-models/metric'); const MetricsRepository = require('./../../src/repositories/metrics'); const promiseMe = require('mocha-promise-me'); const Repository = require('./../../src/repositories/repository'); diff --git a/packages/lambda/test/repositories/nonprofitSlides.js b/packages/lambda/test/repositories/nonprofitSlides.js index 2aec7125..e5a0a2f5 100644 --- a/packages/lambda/test/repositories/nonprofitSlides.js +++ b/packages/lambda/test/repositories/nonprofitSlides.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Slide = require('../../src/models/nonprofitSlide'); +const Slide = require('../../src/dynamo-models/nonprofitSlide'); const NonprofitSlidesRepository = require('../../src/repositories/nonprofitSlides'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/nonprofits.js b/packages/lambda/test/repositories/nonprofits.js index 03acbc4a..318dfe84 100644 --- a/packages/lambda/test/repositories/nonprofits.js +++ b/packages/lambda/test/repositories/nonprofits.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Nonprofit = require('../../src/models/nonprofit'); +const Nonprofit = require('../../src/dynamo-models/nonprofit'); const NonprofitsRepository = require('../../src/repositories/nonprofits'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/paymentTransactions.js b/packages/lambda/test/repositories/paymentTransactions.js index a2c9ff91..4c8dd7f5 100644 --- a/packages/lambda/test/repositories/paymentTransactions.js +++ b/packages/lambda/test/repositories/paymentTransactions.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const PaymentTransaction = require('../../src/models/paymentTransaction'); +const PaymentTransaction = require('../../src/dynamo-models/paymentTransaction'); const PaymentTransactionsRepository = require('../../src/repositories/paymentTransactions'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/reports.js b/packages/lambda/test/repositories/reports.js index 00017b7c..ce1dde64 100644 --- a/packages/lambda/test/repositories/reports.js +++ b/packages/lambda/test/repositories/reports.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const Report = require('../../src/models/report'); +const Report = require('../../src/dynamo-models/report'); const ReportsRepository = require('../../src/repositories/reports'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/settings.js b/packages/lambda/test/repositories/settings.js index d0e8c0e0..179bfd10 100644 --- a/packages/lambda/test/repositories/settings.js +++ b/packages/lambda/test/repositories/settings.js @@ -18,7 +18,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const promiseMe = require('mocha-promise-me'); const Repository = require('./../../src/repositories/repository'); -const Setting = require('./../../src/models/setting'); +const Setting = require('./../../src/dynamo-models/setting'); const SettingsRepository = require('./../../src/repositories/settings'); const TestHelper = require('./../helpers/test'); diff --git a/packages/lambda/test/repositories/sponsorTiers.js b/packages/lambda/test/repositories/sponsorTiers.js index 26876d83..795a957d 100644 --- a/packages/lambda/test/repositories/sponsorTiers.js +++ b/packages/lambda/test/repositories/sponsorTiers.js @@ -17,7 +17,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const Repository = require('../../src/repositories/repository'); -const SponsorTier = require('../../src/models/sponsorTier'); +const SponsorTier = require('../../src/dynamo-models/sponsorTier'); const SponsorTiersRepository = require('../../src/repositories/sponsorTiers'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/sponsors.js b/packages/lambda/test/repositories/sponsors.js index f907e50d..4aa9f34f 100644 --- a/packages/lambda/test/repositories/sponsors.js +++ b/packages/lambda/test/repositories/sponsors.js @@ -17,7 +17,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); const Repository = require('../../src/repositories/repository'); -const Sponsor = require('../../src/models/sponsor'); +const Sponsor = require('../../src/dynamo-models/sponsor'); const SponsorsRepository = require('../../src/repositories/sponsors'); const TestHelper = require('../helpers/test'); diff --git a/packages/lambda/test/repositories/users.js b/packages/lambda/test/repositories/users.js index 6fedaa33..e1a6a32d 100644 --- a/packages/lambda/test/repositories/users.js +++ b/packages/lambda/test/repositories/users.js @@ -16,7 +16,7 @@ const assert = require('assert'); const AWS = require('aws-sdk-mock'); -const User = require('../../src/models/user'); +const User = require('../../src/dynamo-models/user'); const UsersRepository = require('../../src/repositories/users'); const Repository = require('../../src/repositories/repository'); const TestHelper = require('../helpers/test'); From 86e715801e57b75ab94661bb07bfed6649442565 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 24 Aug 2020 09:56:10 -0500 Subject: [PATCH 049/140] GD-1643: Update Contents Repo --- .../templates/givesource-api-contents.yml | 45 ++- .../cloudformation/templates/givesource.yml | 1 + .../components/admin/pages/FAQ.vue | 4 +- .../admin/pages/faq/AddQuestionModal.vue | 4 +- .../admin/pages/faq/DeleteQuestionModal.vue | 2 +- .../admin/pages/faq/FAQListTable.vue | 2 +- packages/lambda/migrations/00_initial.js | 10 +- .../lambda/src/api/deleteContent/index.js | 8 +- .../lambda/src/api/deleteContents/index.js | 17 +- .../lambda/src/api/deleteSettings/index.js | 7 +- packages/lambda/src/api/getContents/index.js | 20 +- packages/lambda/src/api/patchContent/index.js | 2 +- .../lambda/src/api/patchContents/index.js | 20 +- packages/lambda/src/api/postContent/index.js | 15 +- packages/lambda/src/api/postSetting/index.js | 6 +- packages/lambda/src/models/content.js | 31 ++ packages/lambda/src/models/index.js | 4 +- packages/lambda/src/repositories/contents.js | 275 ++++++++++++------ packages/lambda/src/repositories/settings.js | 2 - 19 files changed, 332 insertions(+), 143 deletions(-) create mode 100644 packages/lambda/src/models/content.js diff --git a/packages/cloudformation/templates/givesource-api-contents.yml b/packages/cloudformation/templates/givesource-api-contents.yml index 6d0321f6..e1299fbd 100644 --- a/packages/cloudformation/templates/givesource-api-contents.yml +++ b/packages/cloudformation/templates/givesource-api-contents.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -52,6 +55,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -81,6 +90,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -110,6 +125,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -118,7 +139,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/contents/{content_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/contents/{content_id} DependsOn: PatchContentLambdaFunction PatchContentsLambdaFunction: @@ -139,6 +160,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -168,6 +195,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -176,7 +209,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/contents/{content_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/contents/{content_id} DependsOn: DeleteContentLambdaFunction DeleteContentsLambdaFunction: @@ -197,6 +230,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -222,7 +261,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref ContentsApiResource - PathPart: "{content_uuid}" + PathPart: "{content_id}" GetContentsApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index bec23d3c..0e5bf1d0 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -440,6 +440,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] diff --git a/packages/frontend/src/admin-pages/components/admin/pages/FAQ.vue b/packages/frontend/src/admin-pages/components/admin/pages/FAQ.vue index 32896038..b04966b7 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/FAQ.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/FAQ.vue @@ -111,11 +111,11 @@ }); vue.bus.$on('deleteFAQList', function (data) { - vue.contents = _.reject(vue.contents, {uuid: data.uuid}); + vue.contents = _.reject(vue.contents, {id: data.id}); }); vue.bus.$on('updateFAQList', function (data) { - const index = _.findIndex(vue.contents, {uuid: data.uuid}); + const index = _.findIndex(vue.contents, {id: data.id}); vue.contents[index > -1 ? index : vue.contents.length] = data; }); }, diff --git a/packages/frontend/src/admin-pages/components/admin/pages/faq/AddQuestionModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/faq/AddQuestionModal.vue index a8d5ab02..5879aed8 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/faq/AddQuestionModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/faq/AddQuestionModal.vue @@ -153,11 +153,11 @@ key: 'FAQ_LIST', type: 'COLLECTION' }).then(function (response) { - faqListContent = response.data; + faqListContent = response.data[0]; return vue.$request.patch('contents', { contents: Object.keys(vue.formData).map(function (key) { const content = vue.formData[key]; - content.parentUuid = faqListContent.uuid; + content.parentId = faqListContent.id; return content; }), }); diff --git a/packages/frontend/src/admin-pages/components/admin/pages/faq/DeleteQuestionModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/faq/DeleteQuestionModal.vue index d4eaea9d..adafa3c3 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/faq/DeleteQuestionModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/faq/DeleteQuestionModal.vue @@ -71,7 +71,7 @@ const vue = this; vue.addModal('spinner'); - vue.$request.delete('contents/' + vue.data.content.uuid).then(function () { + vue.$request.delete('contents/' + vue.data.content.id).then(function () { vue.bus.$emit('deleteFAQList', vue.data.content); vue.clearModals(); }); diff --git a/packages/frontend/src/admin-pages/components/admin/pages/faq/FAQListTable.vue b/packages/frontend/src/admin-pages/components/admin/pages/faq/FAQListTable.vue index 7c5b49e7..e4eac2c1 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/faq/FAQListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/faq/FAQListTable.vue @@ -17,7 +17,7 @@ diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 08d67851..5dcb64bd 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -10,6 +10,10 @@ module.exports = { autoIncrement: true, primaryKey: true }, + key: { + type: Sequelize.STRING(2048), + allowNull: false + }, parentId: { type: Sequelize.INTEGER(11), allowNull: false, @@ -25,11 +29,7 @@ module.exports = { allowNull: false, }, value: { - type: Sequelize.STRING(50), - allowNull: false, - }, - name: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, isDeleted: { diff --git a/packages/lambda/src/api/deleteContent/index.js b/packages/lambda/src/api/deleteContent/index.js index dd7185fa..1add4cb7 100644 --- a/packages/lambda/src/api/deleteContent/index.js +++ b/packages/lambda/src/api/deleteContent/index.js @@ -27,14 +27,14 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); request.validate().then(function () { - return repository.get(request.urlParam('content_uuid')); + return repository.get(request.urlParam('content_id')); }).then(function (content) { if (content.type === ContentHelper.TYPE_COLLECTION) { - return repository.batchDeleteByParentUuid(request.urlParam('content_uuid')).then(function () { - return repository.delete(request.urlParam('content_uuid')); + return repository.batchDeleteByParentId(request.urlParam('content_id')).then(function () { + return repository.delete(request.urlParam('content_id')); }); } else { - return repository.delete(request.urlParam('content_uuid')); + return repository.delete(request.urlParam('content_id')); } }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/api/deleteContents/index.js b/packages/lambda/src/api/deleteContents/index.js index e96fc421..75edb723 100644 --- a/packages/lambda/src/api/deleteContents/index.js +++ b/packages/lambda/src/api/deleteContents/index.js @@ -15,7 +15,6 @@ */ const _ = require('lodash'); -const Content = require('./../../dynamo-models/content'); const ContentHelper = require('./../../helpers/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); @@ -30,17 +29,23 @@ exports.handle = function (event, context, callback) { let contents = []; request.validate().then(function () { - request.get('contents', []).forEach(function (data) { - contents.push(new Content(data)); + let promise = Promise.resolve(); + request.get('contents', []).forEach(async function (data) { + promise = promise.then(function () { + return repository.populate(data); + }).then(function (content) { + contents.push(content); + }); }); + return promise; }).then(function () { let promise = Promise.resolve(); contents.forEach(function (content) { - if (content.type === ContentHelper.TYPE_COLLECTION) { + if (content.get('type') === ContentHelper.TYPE_COLLECTION) { promise = promise.then(function () { - return repository.getByParentUuid(content.uuid).then(function (response) { + return repository.getByParentId(content.id).then(function (response) { response.forEach(function (model) { - if (!_.find(contents, {uuid: model.uuid})) { + if (!_.find(contents, {id: model.id})) { contents.push(model); } }); diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index 17cc76eb..74082bf9 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -31,15 +31,16 @@ exports.handle = function (event, context, callback) { return loadModels().then(function (models) { allModels = models; }).then(function () { + let promise = Promise.resolve(); request.get('settings', []).forEach(function (data) { - let promise = Promise.resolve(); - promise.then(function () { - return allModels.Setting.findOne(data).then(function (setting) { + promise = promise.then(function () { + return allModels.Setting.findOne({where: {data}}).then(function (setting) { settings.push(setting); return setting.destroy(); }); }); }); + return promise; }); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/api/getContents/index.js b/packages/lambda/src/api/getContents/index.js index 44f4b378..4432be0d 100644 --- a/packages/lambda/src/api/getContents/index.js +++ b/packages/lambda/src/api/getContents/index.js @@ -29,22 +29,20 @@ exports.handle = function (event, context, callback) { return repository.batchGet(keys); }).then(function (contents) { let promise = Promise.resolve(); + results = []; contents.forEach(function (content) { - const result = content.all(); - if (content.type === ContentHelper.TYPE_COLLECTION) { + if (content.get('type') === ContentHelper.TYPE_COLLECTION) { promise = promise.then(function () { - return repository.getByParentUuid(content.uuid).then(function (response) { - result.value = response.map(function (model) { - return model.all(); - }); - results.push(result); + return repository.getByParentId(content.id); + }).then(function (models) { + let values = []; + models.forEach(function (result) { + values.push(result); }); - }); - } else { - promise = promise.then(function () { - results.push(result); + content.set('value', values); }); } + results.push(content); }); return promise; }).then(function () { diff --git a/packages/lambda/src/api/patchContent/index.js b/packages/lambda/src/api/patchContent/index.js index 82f1af9b..f8356ff0 100644 --- a/packages/lambda/src/api/patchContent/index.js +++ b/packages/lambda/src/api/patchContent/index.js @@ -28,7 +28,7 @@ exports.handle = function (event, context, callback) { let content = null; request.validate().then(function () { - return repository.get(request.urlParam('content_uuid')); + return repository.get(request.urlParam('content_id')); }).then(function (result) { content = new Content(result); content.populate(request._body); diff --git a/packages/lambda/src/api/patchContents/index.js b/packages/lambda/src/api/patchContents/index.js index 51de2d75..2cad77b5 100644 --- a/packages/lambda/src/api/patchContents/index.js +++ b/packages/lambda/src/api/patchContents/index.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); @@ -28,19 +27,26 @@ exports.handle = function (event, context, callback) { let contents = []; request.validate().then(function () { - request.get('contents', []).forEach(function (data) { - contents.push(new Content(data)); + let promise = Promise.resolve(); + request.get('contents', []).map(function (content) { + promise = promise.then(function () { + return repository.populate(content); + }).then(function (model) { + if (Array.isArray(model.get('value'))) { + model.set('value', ''); + } + contents.push(model); + }); }); + return promise; }).then(function () { let promise = Promise.resolve(); - contents.forEach(function (content) { + contents.forEach(function (model) { promise = promise.then(function () { - return content.validate(); + return repository.upsert(model, {}); }); }); return promise; - }).then(function () { - return repository.batchUpdate(contents); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/postContent/index.js b/packages/lambda/src/api/postContent/index.js index 38b0f8de..eef702ac 100644 --- a/packages/lambda/src/api/postContent/index.js +++ b/packages/lambda/src/api/postContent/index.js @@ -26,19 +26,20 @@ exports.handle = function (event, context, callback) { const repository = new ContentsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let content = new Content(request._body); + let content; request.validate().then(function () { + return repository.populate(request._body); + }).then(function (populatedModel) { + content = populatedModel; return repository.getCountByKey(content.key); - }).then(function (count) { - content.populate({sortOrder: count}); - return content.validate(); - }).then(function () { - return repository.save(content); + }).then(function (contents) { + content.set('sortOrder', contents.count); + return repository.upsert(content, {}); }).then(function (response) { content = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - callback(null, content.all()); + callback(null, content); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index d40b900f..ecfd5584 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -34,9 +34,9 @@ exports.handle = function (event, context, callback) { allModels = models; setting = new allModels.Setting(request._body); }).then(function () { - return allModels.Setting.findOne({key: request.get('key')}); - }).then(function (setting) { - if (setting instanceof allModels.Setting) { + return allModels.Setting.findOne({where: {key: request.get('key')}}); + }).then(function (existingSetting) { + if (existingSetting instanceof allModels.Setting) { reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); } else { resolve(); diff --git a/packages/lambda/src/models/content.js b/packages/lambda/src/models/content.js new file mode 100644 index 00000000..b48718a7 --- /dev/null +++ b/packages/lambda/src/models/content.js @@ -0,0 +1,31 @@ +'use strict'; + +const {DataTypes} = require('sequelize'); + +module.exports = (sequelize) => { + return sequelize.define('Content', { + key: { + type: DataTypes.STRING, + allowNull: false + }, + parentId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + sortOrder: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + }, + type: { + type: DataTypes.STRING, + allowNull: false, + }, + value: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '' + } + }); +}; diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js index 7813b58a..a9785544 100644 --- a/packages/lambda/src/models/index.js +++ b/packages/lambda/src/models/index.js @@ -7,7 +7,9 @@ const connect = require('./connect.js'); module.exports = function() { return connect().then(function(sequelize) { const models = {"sequelize": sequelize}; - const model = require('./setting')(sequelize); + let model = require('./setting')(sequelize); + models[model.name] = model; + model = require('./content')(sequelize); models[model.name] = model; return models; }); diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index 0493109f..dc30128f 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -18,7 +18,8 @@ const Content = require('./../dynamo-models/content'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const QueryBuilder = require('./../aws/queryBuilder'); +const loadModels = require('./../models/index'); +const Sequelize = require('sequelize'); /** * ContentsRepository constructor @@ -40,47 +41,75 @@ function ContentsRepository(options) { */ ContentsRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +ContentsRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.Content(data); + }).finally(function () { + return allModels.sequelize.close(); + }) +}; + /** * Get a Content * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -ContentsRepository.prototype.get = function (uuid) { - const repository = this; +ContentsRepository.prototype.get = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.getByKey('uuid', uuid).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new Content(data.Item)); - } - reject(new ResourceNotFoundException('The specified content does not exist.')); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.findOne({ + where: { + id: id + } + }).then(function (content) { + if (content instanceof allModels.Content) { + resolve(content); + } + reject(new ResourceNotFoundException('The specified content does not exist.')); + }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; /** - * Get all contents by parentUuid + * Get all contents by parentId * - * @param {String} parentUuid + * @param {String} parentId * @return {Promise} */ -ContentsRepository.prototype.getByParentUuid = function (parentUuid) { - const repository = this; - const builder = new QueryBuilder('query'); +ContentsRepository.prototype.getByParentId = function (parentId) { + let allModels; return new Promise(function (resolve, reject) { - builder.index('parentUuidIndex').condition('parentUuid', '=', parentUuid); - repository.batchQuery(builder).then(function (data) { - const results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Content(item)); - }); - } + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.findAll({ + where: { + parentId: parentId + } + }); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -92,20 +121,22 @@ ContentsRepository.prototype.getByParentUuid = function (parentUuid) { * @return {Promise} */ ContentsRepository.prototype.getAllByKey = function (key) { - const repository = this; - const builder = new QueryBuilder('query'); + let allModels; return new Promise(function (resolve, reject) { - builder.index('keyIndex').condition('key', '=', key); - repository.batchQuery(builder).then(function (data) { - const results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Content(item)); - }); - } - resolve(results); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.findAll({ + where: { + key: key + } + }).then(function (results) { + resolve(results); + }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -113,38 +144,61 @@ ContentsRepository.prototype.getAllByKey = function (key) { /** * Get Contents by keys * - * @param {[]} keys + * @param {Array} keys * @return {Promise} */ ContentsRepository.prototype.batchGet = function (keys) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - if (!keys) { - reject(new Error('keys is undefined')); - } - - const params = { - FilterExpression: '', - ExpressionAttributeNames: {'#key': 'key'}, - ExpressionAttributeValues: {}, - }; - - keys.forEach(function (key) { - const expression = `#key = :${key}`; - params.FilterExpression = params.FilterExpression ? params.FilterExpression + ' OR ' + expression : expression; - params.ExpressionAttributeValues[`:${key}`] = key; - }); - - repository.batchScan(params).then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Content(item)); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + if (keys.length) { + return allModels.Content.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } + } }); + } else { + return allModels.Content.findAll(); } + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Delete an array of Content models + * + * @param {Array} models + * @returns {Promise} + */ +ContentsRepository.prototype.batchDelete = function (models) { + let allModels; + return new Promise(function (resolve, reject) { + loadModels().then(function (models) { + allModels = models; + }).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.destroy(); + }) + }); + return promise; + }).then(function (stuff) { + resolve(stuff); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -156,14 +210,18 @@ ContentsRepository.prototype.batchGet = function (keys) { * @return {Promise} */ ContentsRepository.prototype.getCountByKey = function (key) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const builder = new QueryBuilder('query'); - builder.index('keyIndex').condition('key', '=', key).select('COUNT'); - repository.batchQuery(builder).then(function (data) { - resolve(data.Count); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.findAndCountAll({where: {key: key}}); + }).then(function (data) { + resolve(data) }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -171,35 +229,45 @@ ContentsRepository.prototype.getCountByKey = function (key) { /** * Delete a Content * - * @param {String} uuid + * @param {String} contentId * @return {Promise} */ -ContentsRepository.prototype.delete = function (uuid) { - const repository = this; +ContentsRepository.prototype.delete = function (contentId) { + let allModels; return new Promise(function (resolve, reject) { - repository.deleteByKey('uuid', uuid).then(function () { - resolve(); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.destroy({where: {id: contentId}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; /** - * Batch delete Contents by parentUuid + * Batch delete Contents by parentId * - * @param {String} parentUuid + * @param {String} parentId * @return {Promise} */ -ContentsRepository.prototype.batchDeleteByParentUuid = function (parentUuid) { - const repository = this; +ContentsRepository.prototype.batchDeleteByParentId = function (parentId) { + let allModels; return new Promise(function (resolve, reject) { - repository.getByParentUuid(parentUuid).then(function (models) { - return repository.batchDelete(models); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.destroy({where: {parentId: parentId}}); }).then(function () { - resolve(); + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -211,14 +279,18 @@ ContentsRepository.prototype.batchDeleteByParentUuid = function (parentUuid) { * @return {Promise} */ ContentsRepository.prototype.batchDeleteByKey = function (key) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - repository.getAllByKey(key).then(function (models) { - return repository.batchDelete(models); + loadModels().then(function (models) { + allModels = models; }).then(function () { - resolve(); + return allModels.Content.destroy({where: {key: key}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -229,17 +301,52 @@ ContentsRepository.prototype.batchDeleteByKey = function (key) { * @param {Content} model */ ContentsRepository.prototype.save = function (model) { + let allModels; const repository = this; return new Promise(function (resolve, reject) { - if (!(model instanceof Content)) { - reject(new Error('invalid Content model')); - } - model.validate().then(function () { - return repository.put({uuid: model.uuid}, model.except(['uuid'])); - }).then(function (data) { - resolve(new Content(data.Attributes)); + loadModels().then(function (models) { + allModels = models; + if (!(model instanceof allModels.Content)) { + reject(new Error('invalid Content model')); + } + return repository.upsert(model, {}); + }).then(function (content) { + resolve(content); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param model + * @param data + * @return {Promise} + */ +ContentsRepository.prototype.upsert = function (model, data) { + let allModels; + return new Promise(function (resolve, reject) { + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Content.upsert({ + 'id': model.get('id'), + 'key': typeof data.key !== "undefined" ? data.key : model.get('key'), + 'value': typeof data.value !== "undefined" ? data.value : model.get('value'), + 'sortOrder': typeof data.sortOrder !== "undefined" ? data.sortOrder : model.get('sortOrder'), + 'type': typeof data.type !== "undefined" ? data.type : model.get('type'), + 'parentId': typeof data.parentId !== "undefined" ? data.parentId : model.get('parentId'), + }); + }).then(function (content) { + resolve(content); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index f3de6a0b..9b323931 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -46,7 +46,6 @@ SettingsRepository.prototype = new Repository(); * @return {Promise} */ SettingsRepository.prototype.get = function (key) { - console.log('key is: ', key); /*DM: Debug */ return Setting.findOne({ where: {key: key}}); }; @@ -56,7 +55,6 @@ SettingsRepository.prototype.get = function (key) { * @return {Promise} */ SettingsRepository.prototype.getAll = function () { - console.log(Setting); /*DM: Debug */ return Setting.findAll(); }; From f4c9ad0ea833055195599f51934758e22f32b315 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 24 Aug 2020 11:01:09 -0500 Subject: [PATCH 050/140] GD-1643: Remove policy --- packages/cloudformation/templates/givesource.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 4b11d4b2..fa8c117e 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -320,14 +320,6 @@ Resources: - ssm:PutParameter Resource: '*' - # TODO: Create a different policy for this - - Effect: Allow - Action: - - secretsmanager:GetSecretValue - Resource: '*' -# Resource: -# - !Ref ReadwriteUserSecret - LambdaRole: Type: AWS::IAM::Role Properties: From b4fd0da501e843d94019bc7b8798f33d8cf97ab2 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 24 Aug 2020 16:33:34 -0500 Subject: [PATCH 051/140] GD-1644: Move settings to repository --- .../lambda/src/api/deleteSetting/index.js | 16 +- .../lambda/src/api/deleteSettings/index.js | 27 ++- packages/lambda/src/api/getSetting/index.js | 2 +- packages/lambda/src/api/getSettings/index.js | 27 +-- packages/lambda/src/api/patchSetting/index.js | 14 +- .../lambda/src/api/patchSettings/index.js | 53 ++---- packages/lambda/src/api/postSetting/index.js | 27 ++- packages/lambda/src/repositories/settings.js | 170 +++++++++++++----- 8 files changed, 186 insertions(+), 150 deletions(-) diff --git a/packages/lambda/src/api/deleteSetting/index.js b/packages/lambda/src/api/deleteSetting/index.js index 83e71233..88a7cf84 100644 --- a/packages/lambda/src/api/deleteSetting/index.js +++ b/packages/lambda/src/api/deleteSetting/index.js @@ -17,25 +17,17 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); +const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); -const loadModels = require('./../../models/index'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); + const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let allModels; request.validate().then(function () { - return loadModels().then(function (models) { - allModels = models; - }).then(function () { - return allModels.Settings.destroy({ - where: { - key: request.urlParam('key') - } - }) - }); + return repository.delete(request.urlParam('key')); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -44,7 +36,5 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); - }).finally(function () { - return allModels.sequelize.close(); }); }; \ No newline at end of file diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index fc388ef2..d4d6a64d 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -17,31 +17,28 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const loadModels = require('../../models/index'); +const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); + const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; - let allModels; request.validate().then(function () { - return loadModels().then(function (models) { - allModels = models; - }).then(function () { - let promise = Promise.resolve(); - request.get('settings', []).forEach(function (data) { - promise = promise.then(function () { - return allModels.Setting.findOne({where: {data}}).then(function (setting) { - settings.push(setting); - return setting.destroy(); - }); - }); + let promise = Promise.resolve(); + request.get('settings', []).forEach(function (data) { + promise = promise.then(function () { + return repository.populate(data); + }).then(function (setting) { + settings.push(setting); }); - return promise; }); + return promise; + }).then(function () { + return repository.batchDeleteByKey(settings); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { @@ -50,7 +47,5 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); - }).finally(function () { - return allModels.sequelize.close(); }); }; \ No newline at end of file diff --git a/packages/lambda/src/api/getSetting/index.js b/packages/lambda/src/api/getSetting/index.js index c35be3fe..15776c34 100644 --- a/packages/lambda/src/api/getSetting/index.js +++ b/packages/lambda/src/api/getSetting/index.js @@ -25,7 +25,7 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return repository.get(request.urlParam('key')); }).then(function (setting) { - callback(null, setting.all()); + callback(null, setting); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getSettings/index.js b/packages/lambda/src/api/getSettings/index.js index 6db5ef40..f4fadb42 100644 --- a/packages/lambda/src/api/getSettings/index.js +++ b/packages/lambda/src/api/getSettings/index.js @@ -16,35 +16,22 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const Sequelize = require('sequelize'); -const loadModels = require('./../../models/index'); +const SettingsRepository = require('./../../repositories/settings'); exports.handle = function (event, context, callback) { + const repository = new SettingsRepository(); const request = new Request(event, context); const keys = request.queryParam('keys', '').split(','); - let allModels; request.validate().then(function () { - return loadModels().then(function (models) { - allModels = models; - }).then(function () { - if (keys.length) { - return allModels.Setting.findAll({ - where: { - key: { - [Sequelize.Op.or]: keys - } - } - }); - } else { - return allModels.Setting.findAll(); - } - }); + if (keys.length) { + return repository.batchGet(keys); + } else { + return repository.getAll(); + } }).then(function (settings) { callback(null, settings); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); - }).finally(function () { - return allModels.sequelize.close(); }); }; diff --git a/packages/lambda/src/api/patchSetting/index.js b/packages/lambda/src/api/patchSetting/index.js index 9f632055..c454a164 100644 --- a/packages/lambda/src/api/patchSetting/index.js +++ b/packages/lambda/src/api/patchSetting/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Setting = require('./../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); @@ -27,22 +26,21 @@ exports.handle = function (event, context, callback) { const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let setting = null; + let setting; request.validate().then(function () { return repository.get(request.urlParam('key')); - }).then(function (result) { - setting = new Setting(result); - setting.populate(request._body); + }).then(function (setting) { + setting.set('value', request._body.value); return setting.validate(); - }).then(function () { + }).then(function (setting) { return repository.save(setting); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - return DynamicContentHelper.regenerateDynamicContent([setting.key], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); + return DynamicContentHelper.regenerateDynamicContent([setting.get('key')], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); }).then(function () { - callback(null, setting.all()); + callback(null, setting); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index 631ba5a9..5ea1d866 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -15,57 +15,42 @@ */ const _ = require('lodash'); -const Sequelize = require('sequelize'); +const SettingsRepository = require('./../../repositories/settings'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const loadModels = require('../../models/index'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); + const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['settings']); let settings = []; - let allModels; request.validate().then(function () { const keys = request.get('settings', []).map(function (setting) { return setting.key; }); - return loadModels().then(function (models) { - allModels = models; - }).then(function () { - return allModels.Setting.findAll({ - where: { - key: { - [Sequelize.Op.or]: keys - } - } - }); - }); + return repository.batchGet(keys); }).then(function (models) { - request.get('settings', []).forEach(function (data) { - let model = _.find(models, {key: data.key}); - if (model instanceof allModels.Setting) { - model.set('value', data.value); - settings.push(model); - } else { - settings.push(new allModels.Setting(data)); - } - }); - - return settings; - }).then(function (settings) { let promise = Promise.resolve(); - settings.forEach(function (setting) { - if (setting instanceof allModels.Setting) { - promise = promise.then(function () { - return allModels.Setting.upsert(setting.toJSON()); - }); - } + request.get('settings', []).forEach(function (data) { + promise = promise.then(function () { + let model = _.find(models, {key: data.key}); + if (typeof model !== "undefined") { + return model; + } else { + return repository.populate(data); + } + }).then(function (model) { + return repository.upsert(model, data); + }).then(function (savedModel) { + settings.push(savedModel); + }).catch(function (err) { + (err instanceof HttpException) ? callback(err.context(context)) : callback(err); + }); }); - return promise; }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); @@ -75,7 +60,5 @@ exports.handle = function (event, context, callback) { callback(); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); - }).finally(function () { - return allModels.sequelize.close(); }); }; diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index f2b7740d..7b396605 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -18,33 +18,30 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const ResourceAlreadyExistsException = require('./../../exceptions/resourceAlreadyExists'); -const loadModels = require('../../models/index'); +const SettingsRepository = require('./../../repositories/settings'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const DynamicContentHelper = require('./../../helpers/dynamicContent'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); + const repository = new SettingsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); let setting; - let allModels; request.validate().then(function () { return new Promise(function (resolve, reject) { - loadModels().then(function (models) { - allModels = models; - setting = new allModels.Setting(request._body); - }).then(function () { - return allModels.Setting.findOne({where: {key: request.get('key')}}); - }).then(function (existingSetting) { - if (existingSetting instanceof allModels.Setting) { - reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); - } else { - resolve(); - } + repository.get(request.get('key')).then(function () { + reject(new ResourceAlreadyExistsException('The setting: ' + request.get('key') + ' already exists')); + }).catch(function () { + resolve(); }); }); }).then(function () { - return allModels.Setting.create(setting.toJSON()); + return repository.populate(request._body); + }).then(function () { + return setting.validate(); + }).then(function () { + return repository.save(setting); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); @@ -54,7 +51,5 @@ exports.handle = function (event, context, callback) { callback(null, setting); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); - }).finally(function () { - return allModels.sequelize.close(); }); }; \ No newline at end of file diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 9b323931..c33d6b1c 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -17,7 +17,8 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Setting = require('../models/index').Setting; +const loadModels = require('../models/index'); +const Sequelize = require('sequelize'); /** * SettingsRepository constructor @@ -39,6 +40,22 @@ function SettingsRepository(options) { */ SettingsRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +SettingsRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.Setting(data); + }).finally(function () { + return allModels.sequelize.close(); + }) +}; + /** * Get a Setting * @@ -46,7 +63,27 @@ SettingsRepository.prototype = new Repository(); * @return {Promise} */ SettingsRepository.prototype.get = function (key) { - return Setting.findOne({ where: {key: key}}); + let allModels; + return new Promise(function (resolve, reject) { + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.findOne({ + where: { + key: key + } + }).then(function (setting) { + if (setting instanceof allModels.Setting) { + resolve(setting); + } + reject(new ResourceNotFoundException('The specified setting does not exist.')); + }); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); }; /** @@ -55,7 +92,20 @@ SettingsRepository.prototype.get = function (key) { * @return {Promise} */ SettingsRepository.prototype.getAll = function () { - return Setting.findAll(); + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.findAll(); + }).then(function (results) { + resolve(results); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); }; /** @@ -65,23 +115,24 @@ SettingsRepository.prototype.getAll = function () { * @return {Promise} */ SettingsRepository.prototype.batchGet = function (keys) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - if (!keys) { - reject(new Error('keys is undefined')); - } - const map = []; - keys.forEach(function (value) { - map.push({key: value}); - }); - repository.batchGetKeys(map).then(function (data) { - let results = []; - data.forEach(function (item) { - results.push(new Setting(item)); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.findAll({ + where: { + key: { + [Sequelize.Op.or]: keys + } + } }); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -93,12 +144,18 @@ SettingsRepository.prototype.batchGet = function (keys) { * @return {Promise} */ SettingsRepository.prototype.delete = function (key) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - repository.deleteByKey('key', key).then(function () { - resolve(); + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.destroy({where: {key: key}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -110,23 +167,27 @@ SettingsRepository.prototype.delete = function (key) { * @return {Promise} */ SettingsRepository.prototype.batchDeleteByKey = function (models) { - const repository = this; + let allModels; + const keys = models.forEach(function (model) { + return model.get('key'); + }); return new Promise(function (resolve, reject) { - const requestItems = []; - models = models || []; - models.forEach(function (model) { - requestItems.push({ - DeleteRequest: { - Key: { - key: model.key + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.destroy({ + where: { + key: { + [Sequelize.Op.or]: keys } } - }); - }); - repository.batchWrite(requestItems, 3).then(function (data) { - resolve(data); + }) + }).then(function (stuff) { + resolve(stuff); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -137,22 +198,49 @@ SettingsRepository.prototype.batchDeleteByKey = function (models) { * @param {Setting} model */ SettingsRepository.prototype.save = function (model) { + let allModels; const repository = this; return new Promise(function (resolve, reject) { - if (!(model instanceof Setting)) { - reject(new Error('invalid Setting model')); - } - model.validate().then(function () { - const key = { - key: model.key - }; - repository.put(key, model.except(['key'])).then(function (data) { - resolve(new Setting(data.Attributes)); - }).catch(function (err) { - reject(err); + loadModels().then(function (models) { + allModels = models; + if (!(model instanceof allModels.Setting)) { + reject(new Error('invalid Setting model')); + } + return repository.upsert(model, {}); + }).then(function (content) { + resolve(content); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param {Object} model + * @param {Object} data + * @return {Promise} + */ +SettingsRepository.prototype.upsert = function (model, data) { + let allModels; + return new Promise(function (resolve, reject) { + loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.upsert({ + 'id': model.get('id'), + 'key': typeof data.key !== "undefined" ? data.key : model.get('key'), + 'value': typeof data.value !== "undefined" ? data.value : model.get('value'), }); + }).then(function (setting) { + resolve(setting); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; From 033d8bffeee8c29f529fa6574cbeaa7a7bff0d8a Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 25 Aug 2020 15:40:18 -0500 Subject: [PATCH 052/140] Updating to use the secret ARN rather than the secret ID in the policy --- packages/cloudformation/templates/givesource-aurora.yml | 2 ++ packages/cloudformation/templates/givesource.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 3dc1b928..4bff1da8 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -258,6 +258,8 @@ Resources: Outputs: ReadwriteUserSecret: Value: !Sub ${AWS::StackName}-ReadwriteUserSecret + ReadwriteUserSecretArn: + Value: !Ref ReadwriteUserSecret DatabaseClusterArn: Value: !Ref RDSCluster DatabaseEndpoint: diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 646b2f6c..b460a5ac 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -122,7 +122,7 @@ Resources: Action: - secretsmanager:GetSecretValue Resource: - - !Sub arn:aws:secretsmanager:::secret:${AuroraDbStack.Outputs.ReadwriteUserSecret} + - !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecretArn Roles: - !Ref LambdaRole DependsOn: AuroraDbStack From 8f492bd6137d5d2380b9d71a8e88e17791b00241 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 1 Sep 2020 09:39:16 -0500 Subject: [PATCH 053/140] GD-1643 --- .../templates/givesource-api-settings.yml | 6 ++++++ .../templates/givesource-custom.yml | 9 +++++++++ .../cloudformation/templates/givesource.yml | 1 + .../lambda/src/custom/saveSettings/index.js | 17 +++++----------- packages/lambda/src/repositories/contents.js | 20 +++++++++---------- .../lambda/src/repositories/repository.js | 12 +++++++++++ packages/lambda/src/repositories/settings.js | 12 +++++------ 7 files changed, 49 insertions(+), 28 deletions(-) diff --git a/packages/cloudformation/templates/givesource-api-settings.yml b/packages/cloudformation/templates/givesource-api-settings.yml index 4eb76e5f..dc58bff5 100644 --- a/packages/cloudformation/templates/givesource-api-settings.yml +++ b/packages/cloudformation/templates/givesource-api-settings.yml @@ -70,6 +70,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSettingLambdaInvokePermission: Type: AWS::Lambda::Permission diff --git a/packages/cloudformation/templates/givesource-custom.yml b/packages/cloudformation/templates/givesource-custom.yml index 1e36a55a..4adb7f60 100644 --- a/packages/cloudformation/templates/givesource-custom.yml +++ b/packages/cloudformation/templates/givesource-custom.yml @@ -12,6 +12,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -565,6 +568,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet # Secure Settings KMS Resources diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 6adad826..5b6c539b 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -361,6 +361,7 @@ Resources: StackName: !Ref AWS::StackName RestApi: !Ref RestApi LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] CognitoSnsCallerRoleArn: !GetAtt CognitoSnsCallerRole.Arn AdminPagesS3: !GetAtt S3Stack.Outputs.AdminPagesS3 diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index cc0b9c94..9d530511 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -17,7 +17,6 @@ const _ = require('lodash'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const Setting = require('../../models/setting'); const SettingsRepository = require('./../../repositories/settings'); const S3 = require('./../../aws/s3'); @@ -29,7 +28,7 @@ exports.handle = function (event, context, callback) { return; } - const models = []; + const bulkData = []; const repository = new SettingsRepository(); const settings = JSON.parse(event.ResourceProperties.Settings); let promise = Promise.resolve(); @@ -41,22 +40,16 @@ exports.handle = function (event, context, callback) { const data = {}; data.key = key; data.value = updatedValue; - models.push(new Setting(data)); + data.createdAt = new Date(); + data.updatedAt = new Date(); + bulkData.push(data); }) }); } }); promise = promise.then(function() { - let subPromise = Promise.resolve(); - models.forEach(function (model) { - subPromise = subPromise.then(function () { - return model.validate().then(function () { - return repository.save(model); - }); - }); - }); - return subPromise; + return repository.bulkInsert('Settings', bulkData); }); promise = promise.then(function () { diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index dc30128f..141dcd7d 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -66,7 +66,7 @@ ContentsRepository.prototype.populate = function (data) { ContentsRepository.prototype.get = function (id) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.findOne({ @@ -96,7 +96,7 @@ ContentsRepository.prototype.get = function (id) { ContentsRepository.prototype.getByParentId = function (parentId) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.findAll({ @@ -123,7 +123,7 @@ ContentsRepository.prototype.getByParentId = function (parentId) { ContentsRepository.prototype.getAllByKey = function (key) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.findAll({ @@ -183,7 +183,7 @@ ContentsRepository.prototype.batchGet = function (keys) { ContentsRepository.prototype.batchDelete = function (models) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { let promise = Promise.resolve(); @@ -212,7 +212,7 @@ ContentsRepository.prototype.batchDelete = function (models) { ContentsRepository.prototype.getCountByKey = function (key) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.findAndCountAll({where: {key: key}}); @@ -235,7 +235,7 @@ ContentsRepository.prototype.getCountByKey = function (key) { ContentsRepository.prototype.delete = function (contentId) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.destroy({where: {id: contentId}}); @@ -258,7 +258,7 @@ ContentsRepository.prototype.delete = function (contentId) { ContentsRepository.prototype.batchDeleteByParentId = function (parentId) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.destroy({where: {parentId: parentId}}); @@ -281,7 +281,7 @@ ContentsRepository.prototype.batchDeleteByParentId = function (parentId) { ContentsRepository.prototype.batchDeleteByKey = function (key) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.destroy({where: {key: key}}); @@ -304,7 +304,7 @@ ContentsRepository.prototype.save = function (model) { let allModels; const repository = this; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; if (!(model instanceof allModels.Content)) { reject(new Error('invalid Content model')); @@ -330,7 +330,7 @@ ContentsRepository.prototype.save = function (model) { ContentsRepository.prototype.upsert = function (model, data) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Content.upsert({ diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index 4fe06c08..b4a3f0e2 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -18,6 +18,8 @@ const _ = require('lodash'); const AWS = require('aws-sdk'); const Model = require('./../dynamo-models/model'); const QueryBuilder = require('./../aws/queryBuilder'); +const loadModels = require('../models/index'); +const Sequelize = require('sequelize'); /** * Repository constructor @@ -249,6 +251,16 @@ Repository.prototype.batchWrite = function (requestItems, retries) { }); }; +Repository.prototype.bulkInsert = function (tableName, data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return models.bulkInsert(tableName, data); + }).finally(function () { + return allModels.sequelize.close(); + }); +}; + /** * Batch update models * diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index c33d6b1c..0a98fba6 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -53,7 +53,7 @@ SettingsRepository.prototype.populate = function (data) { return new models.Setting(data); }).finally(function () { return allModels.sequelize.close(); - }) + }); }; /** @@ -65,7 +65,7 @@ SettingsRepository.prototype.populate = function (data) { SettingsRepository.prototype.get = function (key) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Setting.findOne({ @@ -146,7 +146,7 @@ SettingsRepository.prototype.batchGet = function (keys) { SettingsRepository.prototype.delete = function (key) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Setting.destroy({where: {key: key}}); @@ -172,7 +172,7 @@ SettingsRepository.prototype.batchDeleteByKey = function (models) { return model.get('key'); }); return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Setting.destroy({ @@ -201,7 +201,7 @@ SettingsRepository.prototype.save = function (model) { let allModels; const repository = this; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; if (!(model instanceof allModels.Setting)) { reject(new Error('invalid Setting model')); @@ -227,7 +227,7 @@ SettingsRepository.prototype.save = function (model) { SettingsRepository.prototype.upsert = function (model, data) { let allModels; return new Promise(function (resolve, reject) { - loadModels().then(function (models) { + return loadModels().then(function (models) { allModels = models; }).then(function () { return allModels.Setting.upsert({ From b058611237afa8c5e8574282ac37872a7e56afbb Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Tue, 1 Sep 2020 15:54:27 -0500 Subject: [PATCH 054/140] [GD-1641] Enable and enforce ssl for all mysql connections * Pass the ca cert in the connection options * You cannot force the users to connect with SSL via the REQUIRE SSL syntax on aurora serverless --- .../src/database/bootstrapDatabase/index.js | 24 ++++++++++++++--- .../src/database/migrateDatabase/index.js | 23 ++++++++++++++-- packages/lambda/src/models/connect.js | 27 ++++++++++++++++--- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/packages/lambda/src/database/bootstrapDatabase/index.js b/packages/lambda/src/database/bootstrapDatabase/index.js index 47c6e47e..059a4fe5 100644 --- a/packages/lambda/src/database/bootstrapDatabase/index.js +++ b/packages/lambda/src/database/bootstrapDatabase/index.js @@ -20,6 +20,26 @@ const Request = require('./../../aws/request'); const SecretsManager = require('./../../aws/secretsManager'); const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); +const cacert = `-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE-----`; exports.handle = function (event, context, callback) { logger.log('bootstrapDatabase event: %j', event); @@ -54,14 +74,12 @@ exports.handle = function (event, context, callback) { dialect: 'mysql', dialectModule: mysql2, logging: false, // don't log the sql so we don't log the passwords - ssl: true, dialectOptions: { - ssl: 'Amazon RDS', + ssl: {ca: cacert}, multipleStatements: true } }); - // TODO: Add REQUIRE SSL to the grants return sequelize.query( 'CREATE DATABASE IF NOT EXISTS `' + dbName + '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; ' + 'CREATE USER IF NOT EXISTS "' + maintenanceSecret.username + '"@"%" IDENTIFIED BY "' + maintenanceSecret.password + '"; ' + diff --git a/packages/lambda/src/database/migrateDatabase/index.js b/packages/lambda/src/database/migrateDatabase/index.js index 150e8643..c1ccb801 100644 --- a/packages/lambda/src/database/migrateDatabase/index.js +++ b/packages/lambda/src/database/migrateDatabase/index.js @@ -24,6 +24,26 @@ const SecretsManager = require('./../../aws/secretsManager'); const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); const Umzug = require('umzug'); +const cacert = `-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE-----`; exports.handle = function (event, context, callback) { logger.log('migrateDatabase event: %j', event); @@ -59,9 +79,8 @@ exports.handle = function (event, context, callback) { dialect: 'mysql', dialectModule: mysql2, port: 3306, - ssl: true, dialectOptions: { - ssl: 'Amazon RDS' + ssl: {ca: cacert} } }); diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index e7b951e7..c9b78799 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -20,6 +20,28 @@ const CloudFormation = require('../aws/cloudformation'); const SecretsManager = require('../aws/secretsManager'); const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); +const cacert = `-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE-----`; + + module.exports = function() { const cloudFormation = new CloudFormation(); @@ -37,13 +59,10 @@ module.exports = function() { port: readwriteSecret.port, dialect: 'mysql', dialectModule: mysql2, - ssl: true, dialectOptions: { - ssl: 'Amazon RDS', + ssl: {ca: cacert}, connectTimeout: 60000 } }); - }).then(function (sequelize) { - return sequelize; }); }; From f465715bb8ea97716e565dba743d9f8ed9c41b0f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 1 Sep 2020 16:45:26 -0500 Subject: [PATCH 055/140] GD-1645: Update Sponsors Repository --- .../templates/givesource-api-deploy.yml | 2 +- .../templates/givesource-api-files.yml | 39 ++- .../templates/givesource-api-sponsors.yml | 109 ++++++-- .../cloudformation/templates/givesource.yml | 2 + .../admin/sponsorTiers/SponsorsTiersEdit.vue | 8 +- .../sponsorTiers/SponsorsTiersListTable.vue | 6 +- .../SponsorsTiersListTableRow.vue | 20 +- .../sponsorTiers/sponsors/SponsorAdd.vue | 26 +- .../sponsorTiers/sponsors/SponsorEdit.vue | 40 +-- .../sponsorTiers/sponsors/SponsorsList.vue | 32 +-- .../sponsors/SponsorsListTable.vue | 14 +- .../sponsors/SponsorsListTableRow.vue | 10 +- .../components/forms/SponsorTier.vue | 2 +- .../frontend/src/admin-pages/router/index.js | 8 +- .../components/layout/Sponsors.vue | 28 +-- packages/lambda/migrations/00_initial.js | 19 +- packages/lambda/src/api/deleteFile/index.js | 2 +- .../lambda/src/api/deleteSponsor/index.js | 2 +- .../lambda/src/api/deleteSponsorTier/index.js | 2 +- .../lambda/src/api/deleteSponsors/index.js | 2 +- packages/lambda/src/api/getFile/index.js | 4 +- packages/lambda/src/api/getFiles/index.js | 11 +- packages/lambda/src/api/getSponsor/index.js | 4 +- .../lambda/src/api/getSponsorTier/index.js | 4 +- .../lambda/src/api/getSponsorTiers/index.js | 5 +- packages/lambda/src/api/getSponsors/index.js | 7 +- packages/lambda/src/api/patchSponsor/index.js | 4 +- .../lambda/src/api/patchSponsorTier/index.js | 2 +- .../lambda/src/api/patchSponsors/index.js | 15 +- packages/lambda/src/api/postFile/index.js | 18 +- packages/lambda/src/api/postSponsor/index.js | 16 +- .../lambda/src/api/postSponsorTier/index.js | 13 +- .../lambda/src/custom/saveSettings/index.js | 2 +- packages/lambda/src/models/file.js | 32 +++ packages/lambda/src/models/index.js | 6 + packages/lambda/src/models/sponsor.js | 60 +++++ packages/lambda/src/models/sponsorTier.js | 48 ++++ packages/lambda/src/repositories/files.js | 124 ++++++--- .../lambda/src/repositories/repository.js | 67 +++-- packages/lambda/src/repositories/settings.js | 26 +- .../lambda/src/repositories/sponsorTiers.js | 140 ++++++++--- packages/lambda/src/repositories/sponsors.js | 235 ++++++++++++------ 42 files changed, 844 insertions(+), 372 deletions(-) create mode 100644 packages/lambda/src/models/file.js create mode 100644 packages/lambda/src/models/sponsor.js create mode 100644 packages/lambda/src/models/sponsorTier.js diff --git a/packages/cloudformation/templates/givesource-api-deploy.yml b/packages/cloudformation/templates/givesource-api-deploy.yml index 2558f780..fc417fd5 100644 --- a/packages/cloudformation/templates/givesource-api-deploy.yml +++ b/packages/cloudformation/templates/givesource-api-deploy.yml @@ -79,7 +79,7 @@ Resources: CacheDataEncrypted: true CacheTtlInSeconds: 300 CachingEnabled: true - - ResourcePath: "/sponsor-tiers/{sponsor_tier_uuid}/sponsors" + - ResourcePath: "/sponsor-tiers/{sponsor_tier_id}/sponsors" HttpMethod: GET CacheDataEncrypted: true CacheTtlInSeconds: 300 diff --git a/packages/cloudformation/templates/givesource-api-files.yml b/packages/cloudformation/templates/givesource-api-files.yml index 190d24e5..014c9534 100644 --- a/packages/cloudformation/templates/givesource-api-files.yml +++ b/packages/cloudformation/templates/givesource-api-files.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -55,6 +58,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -63,7 +72,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/files/{file_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/files/{file_id} DependsOn: GetFileLambdaFunction GetFilesLambdaFunction: @@ -84,6 +93,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetFilesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -114,6 +129,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -144,6 +165,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -152,7 +179,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/files/{file_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/files/{file_id} DependsOn: DeleteFileLambdaFunction DeleteFilesLambdaFunction: @@ -174,6 +201,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteFilesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -199,7 +232,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref FilesApiResource - PathPart: "{file_uuid}" + PathPart: "{file_id}" GetFileApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource-api-sponsors.yml b/packages/cloudformation/templates/givesource-api-sponsors.yml index 4f797ce9..3a01b03f 100644 --- a/packages/cloudformation/templates/givesource-api-sponsors.yml +++ b/packages/cloudformation/templates/givesource-api-sponsors.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -52,6 +55,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -60,7 +69,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id} DependsOn: GetSponsorTierLambdaFunction GetSponsorTiersLambdaFunction: @@ -81,6 +90,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -110,6 +125,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -139,6 +160,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -147,7 +174,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id} DependsOn: PatchSponsorTierLambdaFunction PatchSponsorTiersLambdaFunction: @@ -168,6 +195,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -197,6 +230,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -205,7 +244,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id} DependsOn: DeleteSponsorTierLambdaFunction # Sponsors Lambda Resources @@ -228,6 +267,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -236,7 +281,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: GetSponsorLambdaFunction GetSponsorsLambdaFunction: @@ -257,6 +302,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -265,7 +316,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: GetSponsorsLambdaFunction PostSponsorLambdaFunction: @@ -286,6 +337,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -294,7 +351,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: PostSponsorLambdaFunction PatchSponsorLambdaFunction: @@ -315,6 +372,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -323,7 +386,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: PatchSponsorLambdaFunction PatchSponsorsLambdaFunction: @@ -344,6 +407,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -352,7 +421,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: PatchSponsorsLambdaFunction DeleteSponsorLambdaFunction: @@ -373,6 +442,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -381,7 +456,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: DeleteSponsorLambdaFunction DeleteSponsorsLambdaFunction: @@ -402,6 +477,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -410,7 +491,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: DeleteSponsorsLambdaFunction # Sponsor Tiers Api Gateway Resources @@ -427,7 +508,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref SponsorTiersApiResource - PathPart: "{sponsor_tier_uuid}" + PathPart: "{sponsor_tier_id}" GetSponsorTierApiMethod: Type: AWS::ApiGateway::Method @@ -941,7 +1022,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref SponsorsApiResource - PathPart: "{sponsor_uuid}" + PathPart: "{sponsor_id}" GetSponsorApiMethod: Type: AWS::ApiGateway::Method @@ -1025,14 +1106,14 @@ Resources: ApiKeyRequired: false RequestParameters: method.request.querystring.c: false - method.request.path.sponsor_tier_uuid: true + method.request.path.sponsor_tier_id: true Integration: Type: AWS IntegrationHttpMethod: POST PassthroughBehavior: NEVER CacheKeyParameters: - method.request.querystring.c - - method.request.path.sponsor_tier_uuid + - method.request.path.sponsor_tier_id RequestTemplates: application/json: !Ref IntegrationRequestTemplate Uri: !Sub diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 5b6c539b..93e45c02 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -511,6 +511,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -662,6 +663,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersEdit.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersEdit.vue index 6b740ee9..8cfe3c28 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersEdit.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersEdit.vue @@ -108,11 +108,11 @@ }; }, props: [ - 'sponsorTierUuid' + 'sponsorTierId' ], beforeRouteEnter: function (to, from, next) { next(function (vue) { - vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid).then(function (response) { + vue.$request.get('sponsor-tiers/' + vue.sponsorTierId).then(function (response) { vue.sponsorTier = response.data; }).catch(function (err) { vue.apiError = err.response.data.errors; @@ -122,7 +122,7 @@ beforeRouteUpdate: function (to, from, next) { const vue = this; - vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid).then(function (response) { + vue.$request.get('sponsor-tiers/' + vue.sponsorTierId).then(function (response) { vue.sponsorTier = response.data; next(); }).catch(function (err) { @@ -183,7 +183,7 @@ return; } - vue.$request.patch('sponsor-tiers/' + vue.sponsorTierUuid, params).then(function (response) { + vue.$request.patch('sponsor-tiers/' + vue.sponsorTierId, params).then(function (response) { vue.clearModals(); if (response.data.errorMessage) { console.log(response.data); diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTable.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTable.vue index 428c8eb7..e5d03d7f 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTable.vue @@ -25,7 +25,7 @@ - @@ -83,11 +83,11 @@ vue.$emit('hasError', err); }); }, - deleteSponsorTier: function (sponsorTierUuid) { + deleteSponsorTier: function (sponsorTierId) { const vue = this; vue.localSponsorTiers = _.filter(vue.localSponsorTiers, function (sponsorTier) { - return sponsorTier.uuid !== sponsorTierUuid; + return sponsorTier.id !== sponsorTierId; }); }, hasError: function (err) { diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue index d0595fd4..76f9d10e 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue @@ -26,13 +26,13 @@
- + Manage Tier
- + Edit Tier Settings
@@ -96,30 +96,30 @@ vue.addModal('spinner'); const sponsors = []; - const fileUuids = []; - vue.$request.get('sponsor-tiers/' + vue.sponsorTier.uuid + '/sponsors').then(function (response) { + const fileIds = []; + vue.$request.get('sponsor-tiers/' + vue.sponsorTier.id + '/sponsors').then(function (response) { response.data.forEach(function (sponsor) { sponsors.push(sponsor); - if (sponsor.fileUuid) { - fileUuids.push(sponsor.fileUuid); + if (sponsor.fileId) { + fileIds.push(sponsor.fileId); } }); return vue.$request.get('files', { - uuids: fileUuids + uuids: fileIds }); }).then(function (response) { return vue.$request.delete('files', { files: response.data }); }).then(function () { - return vue.$request.delete('sponsor-tiers/' + vue.sponsorTier.uuid + '/sponsors', { + return vue.$request.delete('sponsor-tiers/' + vue.sponsorTier.id + '/sponsors', { sponsors: sponsors }); }).then(function () { - return vue.$request.delete('sponsor-tiers/' + vue.sponsorTier.uuid); + return vue.$request.delete('sponsor-tiers/' + vue.sponsorTier.id); }).then(function () { vue.clearModals(); - vue.$emit('deleteSponsorTier', vue.sponsorTier.uuid); + vue.$emit('deleteSponsorTier', vue.sponsorTier.id); }).catch(function (err) { vue.clearModals(); vue.$emit('hasError', err); diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorAdd.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorAdd.vue index 1f6af4fa..309572ae 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorAdd.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorAdd.vue @@ -62,15 +62,15 @@
-
+
- -
- {{ formErrors.sponsorTierUuid }} + +
+ {{ formErrors.sponsorTierId }}
@@ -118,7 +118,7 @@ formData: { file: null, name: null, - sponsorTierUuid: this.sponsorTierUuid ? this.sponsorTierUuid : null, + sponsorTierId: this.sponsorTierId ? this.sponsorTierId : null, url: null, }, @@ -128,7 +128,7 @@ }; }, props: { - sponsorTierUuid: null, + sponsorTierId: null, }, beforeRouteEnter: function (to, from, next) { next(function (vue) { @@ -137,7 +137,7 @@ return a.sortOrder - b.sortOrder; }); vue.sponsorTiers = response.data; - vue.sponsorTier = _.find(vue.sponsorTiers, {uuid: to.params.sponsorTierUuid}); + vue.sponsorTier = _.find(vue.sponsorTiers, {id: parseInt(to.params.sponsorTierId)}); }); }); }, @@ -176,7 +176,7 @@ name: { presence: true, }, - sponsorTierUuid: { + sponsorTierId: { label: 'Tier', presence: true, }, @@ -226,10 +226,10 @@ } promise.then(function () { - return vue.$request.post('sponsor-tiers/' + vue.formData.sponsorTierUuid + '/sponsors', { - fileUuid: file && file.hasOwnProperty('uuid') ? file.uuid : null, + return vue.$request.post('sponsor-tiers/' + vue.formData.sponsorTierId + '/sponsors', { + fileId: file && file.hasOwnProperty('id') ? file.id : null, name: vue.formData.name, - sponsorTierUuid: vue.formData.sponsorTierUuid, + sponsorTierId: vue.formData.sponsorTierId, url: vue.formData.url }); }).then(function (response) { @@ -242,7 +242,7 @@ vue.formData = { file: null, name: null, - sponsorTierUuid: vue.sponsorTierUuid, + sponsorTierId: vue.sponsorTierId, url: null }; } else { diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorEdit.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorEdit.vue index 7987b245..cede619d 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorEdit.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorEdit.vue @@ -63,15 +63,15 @@
-
+
- -
- {{ formErrors.sponsorTierUuid }} + +
+ {{ formErrors.sponsorTierId }}
@@ -120,7 +120,7 @@ formData: { file: null, name: '', - sponsorTierUuid: this.sponsorTierUuid, + sponsorTierId: this.sponsorTierId, url: '', }, @@ -130,8 +130,8 @@ }; }, props: { - sponsorUuid: null, - sponsorTierUuid: null, + sponsorId: null, + sponsorTierId: null, }, beforeRouteEnter: function (to, from, next) { next(function (vue) { @@ -140,11 +140,11 @@ return a.sortOrder - b.sortOrder; }); vue.sponsorTiers = response.data; - return vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors/' + vue.sponsorUuid); + return vue.$request.get('sponsor-tiers/' + vue.sponsorTierId + '/sponsors/' + vue.sponsorId); }).then(function (response) { vue.sponsor = response.data; - vue.sponsorTier = _.find(vue.sponsorTiers, {uuid: vue.sponsor.sponsorTierUuid}); - return (vue.sponsor.fileUuid) ? vue.$request.get('files/' + vue.sponsor.fileUuid) : Promise.resolve(); + vue.sponsorTier = _.find(vue.sponsorTiers, {id: vue.sponsor.sponsorTierId}); + return (vue.sponsor.fileId) ? vue.$request.get('files/' + vue.sponsor.fileId) : Promise.resolve(); }).then(function (response) { if (response) { vue.file = response.data; @@ -162,11 +162,11 @@ return a.sortOrder - b.sortOrder; }); vue.sponsorTiers = response.data; - return vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors/' + vue.sponsorUuid); + return vue.$request.get('sponsor-tiers/' + vue.sponsorTierId + '/sponsors/' + vue.sponsorId); }).then(function (response) { vue.sponsor = response.data; - vue.sponsorTier = _.find(vue.sponsorTiers, {uuid: vue.sponsor.sponsorTierUuid}); - return (vue.sponsor.fileUuid) ? vue.$request.get('files/' + vue.sponsor.fileUuid) : Promise.resolve(); + vue.sponsorTier = _.find(vue.sponsorTiers, {id: vue.sponsor.sponsorTierId}); + return (vue.sponsor.fileId) ? vue.$request.get('files/' + vue.sponsor.fileId) : Promise.resolve(); }).then(function (response) { if (response) { vue.file = response.data; @@ -209,7 +209,7 @@ name: { presence: true, }, - sponsorTierUuid: { + sponsorTierId: { label: 'Tier', presence: true, }, @@ -237,8 +237,8 @@ let promise = Promise.resolve(); if (vue.formData.file instanceof File) { - if (vue.file.hasOwnProperty('uuid')) { - promise = vue.$request.delete('files/' + vue.file.uuid); + if (vue.file.hasOwnProperty('id')) { + promise = vue.$request.delete('files/' + vue.file.id); } promise = promise.then(function () { @@ -261,11 +261,11 @@ promise.then(function () { const params = vue.getUpdatedParameters(vue.formData, vue.sponsor); - if (vue.file.hasOwnProperty('uuid')) { - params.fileUuid = vue.file.uuid; + if (vue.file.hasOwnProperty('id')) { + params.fileId = vue.file.id; } - return vue.$request.patch('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors/' + vue.sponsorUuid, params); + return vue.$request.patch('sponsor-tiers/' + vue.sponsorTierId + '/sponsors/' + vue.sponsorId, params); }).then(function () { vue.$store.commit('generateCacheKey'); vue.clearModals(); diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsList.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsList.vue index bdceb251..3cbd00d6 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsList.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsList.vue @@ -38,7 +38,7 @@
- +
@@ -61,22 +61,22 @@ }, beforeRouteEnter: function (to, from, next) { next(function (vue) { - vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid).then(function (response) { + vue.$request.get('sponsor-tiers/' + vue.sponsorTierId).then(function (response) { vue.sponsorTier = response.data; - return vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors'); + return vue.$request.get('sponsor-tiers/' + vue.sponsorTierId + '/sponsors'); }).then(function (response) { response.data.sort(function (a, b) { return a.sortOrder - b.sortOrder; }); vue.sponsors = response.data; - const uuids = []; + const fileIds = []; vue.sponsors.forEach(function (sponsor) { - if (sponsor.fileUuid) { - uuids.push(sponsor.fileUuid); + if (sponsor.fileId) { + fileIds.push(sponsor.fileId); } }); - if (uuids.length) { - return vue.$request.get('files', {uuids: uuids}); + if (fileIds.length) { + return vue.$request.get('files', {fileIds: fileIds}); } else { return Promise.resolve(); } @@ -88,22 +88,22 @@ beforeRouteUpdate: function (to, from, next) { const vue = this; - vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid).then(function (response) { + vue.$request.get('sponsor-tiers/' + vue.sponsorTierId).then(function (response) { vue.sponsorTier = response.data; - return vue.$request.get('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors'); + return vue.$request.get('sponsor-tiers/' + vue.sponsorTierId + '/sponsors'); }).then(function (response) { response.data.sort(function (a, b) { return a.sortOrder - b.sortOrder; }); vue.sponsors = response.data; - const uuids = []; + const fileIds = []; vue.sponsors.forEach(function (sponsor) { - if (sponsor.fileUuid) { - uuids.push(sponsor.fileUuid); + if (sponsor.fileId) { + fileIds.push(sponsor.fileId); } }); - if (uuids.length) { - return vue.$request.get('files', {uuids: uuids}); + if (fileIds.length) { + return vue.$request.get('files', {fileIds: fileIds}); } else { return Promise.resolve(); } @@ -116,7 +116,7 @@ }); }, props: [ - 'sponsorTierUuid' + 'sponsorTierId' ], methods: { hasError: function (err) { diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue index ca182f25..0db6af5f 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue @@ -26,7 +26,7 @@ - @@ -63,7 +63,7 @@ return []; } }, - sponsorTierUuid: { + sponsorTierId: { type: String, default: null, } @@ -77,8 +77,8 @@ }, }, methods: { - getFile: function (fileUuid) { - return _.find(this.files, {uuid: fileUuid}); + getFile: function (fileId) { + return _.find(this.files, {id: fileId}); }, updateSortOrder: function () { const vue = this; @@ -89,17 +89,17 @@ }); const toUpdate = _.differenceWith(vue.localSponsors, original, _.isEqual); - vue.$request.patch('sponsor-tiers/' + vue.sponsorTierUuid + '/sponsors', { + vue.$request.patch('sponsor-tiers/' + vue.sponsorTierId + '/sponsors', { sponsors: toUpdate }).catch(function (err) { vue.$emit('hasError', err); }); }, - deleteSponsor: function (sponsorUuid) { + deleteSponsor: function (sponsorId) { const vue = this; vue.localSponsors = _.filter(vue.localSponsors, function (sponsor) { - return sponsor.uuid !== sponsorUuid; + return sponsor.id !== sponsorId; }); }, hasError: function (err) { diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTableRow.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTableRow.vue index e6b6a096..064d5056 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTableRow.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTableRow.vue @@ -26,7 +26,7 @@ - {{ sponsor.name }} + {{ sponsor.name }} @@ -66,15 +66,15 @@ vue.addModal('spinner'); let promise = Promise.resolve(); - if (vue.sponsor.hasOwnProperty('fileUuid') && vue.sponsor.fileUuid) { - promise = vue.$request.delete('files/' + vue.sponsor.fileUuid); + if (vue.sponsor.hasOwnProperty('fileId') && vue.sponsor.fileId) { + promise = vue.$request.delete('files/' + vue.sponsor.fileId); } promise.then(function () { - return vue.$request.delete('sponsor-tiers/' + vue.sponsor.sponsorTierUuid + '/sponsors/' + vue.sponsor.uuid); + return vue.$request.delete('sponsor-tiers/' + vue.sponsor.sponsorTierId + '/sponsors/' + vue.sponsor.id); }).then(function () { vue.clearModals(); - vue.$emit('deleteSponsor', vue.sponsor.uuid); + vue.$emit('deleteSponsor', vue.sponsor.id); }).catch(function (err) { vue.clearModals(); vue.$emit('hasError', err); diff --git a/packages/frontend/src/admin-pages/components/forms/SponsorTier.vue b/packages/frontend/src/admin-pages/components/forms/SponsorTier.vue index 2c2a2bb4..fa8a0ed6 100644 --- a/packages/frontend/src/admin-pages/components/forms/SponsorTier.vue +++ b/packages/frontend/src/admin-pages/components/forms/SponsorTier.vue @@ -18,7 +18,7 @@ diff --git a/packages/frontend/src/admin-pages/router/index.js b/packages/frontend/src/admin-pages/router/index.js index d2dbef26..fa212982 100644 --- a/packages/frontend/src/admin-pages/router/index.js +++ b/packages/frontend/src/admin-pages/router/index.js @@ -361,7 +361,7 @@ const router = new VueRouter({ } }, { - path: '/sponsor-tiers/:sponsorTierUuid', + path: '/sponsor-tiers/:sponsorTierId', name: 'sponsor-tiers-edit', props: true, component: ComponentSponsorTiersEdit, @@ -370,7 +370,7 @@ const router = new VueRouter({ } }, { - path: '/sponsor-tiers/:sponsorTierUuid/sponsors', + path: '/sponsor-tiers/:sponsorTierId/sponsors', name: 'sponsors-list', props: true, component: ComponentSponsorsList, @@ -379,7 +379,7 @@ const router = new VueRouter({ } }, { - path: '/sponsor-tiers/:sponsorTierUuid/add', + path: '/sponsor-tiers/:sponsorTierId/add', name: 'sponsors-add', props: true, component: ComponentSponsorAdd, @@ -388,7 +388,7 @@ const router = new VueRouter({ } }, { - path: '/sponsor-tiers/:sponsorTierUuid/sponsors/:sponsorUuid', + path: '/sponsor-tiers/:sponsorTierId/sponsors/:sponsorId', name: 'sponsors-edit', props: true, component: ComponentSponsorEdit, diff --git a/packages/frontend/src/public-pages/components/layout/Sponsors.vue b/packages/frontend/src/public-pages/components/layout/Sponsors.vue index d7c681b7..daa2f729 100644 --- a/packages/frontend/src/public-pages/components/layout/Sponsors.vue +++ b/packages/frontend/src/public-pages/components/layout/Sponsors.vue @@ -18,18 +18,18 @@

Many Thanks To Our Sponsors

-
+

{{ sponsorTier.name }}

- @@ -66,14 +66,14 @@ let promise = Promise.resolve(); vue.sponsorTiers.forEach(function (sponsorTier) { promise = promise.then(function () { - return axios.get(API_URL + 'sponsor-tiers/' + sponsorTier.uuid + '/sponsors').then(function (response) { + return axios.get(API_URL + 'sponsor-tiers/' + sponsorTier.id + '/sponsors').then(function (response) { response.data.sort(function (a, b) { return a.sortOrder - b.sortOrder; }); - vue.sponsors[sponsorTier.uuid] = response.data; + vue.sponsors[sponsorTier.id] = response.data; response.data.forEach(function (sponsor) { - if (sponsor.fileUuid) { - vue.files[sponsor.fileUuid] = {}; + if (sponsor.fileId) { + vue.files[sponsor.fileId] = {}; } }); }); @@ -81,16 +81,16 @@ }); return promise; }).then(function () { - const fileUuids = Object.keys(vue.files); - if (fileUuids.length) { - return axios.get(API_URL + 'files' + Utils.generateQueryString({uuids: fileUuids})); + const fileIds = Object.keys(vue.files); + if (fileIds.length) { + return axios.get(API_URL + 'files' + Utils.generateQueryString({fileIds: fileIds})); } else { return Promise.resolve(); } }).then(function (response) { if (response && response.data) { response.data.forEach(function (file) { - vue.files[file.uuid] = file; + vue.files[file.id] = file; }); } }).then(function () { @@ -108,10 +108,10 @@ return 'sponsors__tier--md'; } }, - getSponsorImage: function (fileUuid) { + getSponsorImage: function (fileId) { const vue = this; - const file = vue.files[fileUuid]; + const file = vue.files[fileId]; return file.hasOwnProperty('path') ? vue.$store.getters.setting('UPLOADS_CLOUD_FRONT_URL') + '/' + file.path : false; } } diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 5dcb64bd..7063da5b 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -217,7 +217,7 @@ module.exports = { primaryKey: true }, path: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, filename: { @@ -681,11 +681,11 @@ module.exports = { primaryKey: true }, logoUrl: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, name: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, sortOrder: { @@ -694,7 +694,7 @@ module.exports = { defaultValue: 0 }, url: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, fileId: { @@ -705,7 +705,12 @@ module.exports = { sponsorTierId: { type: Sequelize.INTEGER(11), allowNull: false, - defaultValue: 0 + defaultValue: 0, + references: { + model: 'SponsorTiers', + key: 'id', + as: 'sponsorTierId' + } }, isDeleted: { type: Sequelize.BOOLEAN, @@ -731,11 +736,11 @@ module.exports = { primaryKey: true }, name: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, size: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false, }, sortOrder: { diff --git a/packages/lambda/src/api/deleteFile/index.js b/packages/lambda/src/api/deleteFile/index.js index ce1b1c0b..19b746a6 100644 --- a/packages/lambda/src/api/deleteFile/index.js +++ b/packages/lambda/src/api/deleteFile/index.js @@ -29,7 +29,7 @@ exports.handle = function (event, context, callback) { let file = null; request.validate().then(function () { - return repository.get(request.urlParam('file_uuid')); + return repository.get(request.urlParam('file_id')); }).then(function (model) { file = model; return s3.deleteObject(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, `uploads/${file.uuid}`); diff --git a/packages/lambda/src/api/deleteSponsor/index.js b/packages/lambda/src/api/deleteSponsor/index.js index 69df9055..ca4920c1 100644 --- a/packages/lambda/src/api/deleteSponsor/index.js +++ b/packages/lambda/src/api/deleteSponsor/index.js @@ -26,7 +26,7 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); request.validate().then(function () { - return repository.delete(request.urlParam('sponsor_tier_uuid'), request.urlParam('sponsor_uuid')); + return repository.delete(request.urlParam('sponsor_tier_id'), request.urlParam('sponsor_id')); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/deleteSponsorTier/index.js b/packages/lambda/src/api/deleteSponsorTier/index.js index cf213976..58a2565a 100644 --- a/packages/lambda/src/api/deleteSponsorTier/index.js +++ b/packages/lambda/src/api/deleteSponsorTier/index.js @@ -26,7 +26,7 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); request.validate().then(function () { - return repository.delete(request.urlParam('sponsor_tier_uuid')); + return repository.delete(request.urlParam('sponsor_tier_id')); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index 4a154a5c..ec2c0f64 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -32,7 +32,7 @@ exports.handle = function (event, context, callback) { sponsors.push(new Sponsor(data)); }); }).then(function () { - return repository.batchRemove(request.urlParam('sponsor_tier_uuid'), sponsors); + return repository.batchRemove(request.urlParam('sponsor_tier_id'), sponsors); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/getFile/index.js b/packages/lambda/src/api/getFile/index.js index f8bef144..a0f71b0f 100644 --- a/packages/lambda/src/api/getFile/index.js +++ b/packages/lambda/src/api/getFile/index.js @@ -23,9 +23,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.validate().then(function () { - return repository.get(request.urlParam('file_uuid')); + return repository.get(request.urlParam('file_id')); }).then(function (file) { - callback(null, file.all()); + callback(null, file); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getFiles/index.js b/packages/lambda/src/api/getFiles/index.js index ce9075da..9bc7bffb 100644 --- a/packages/lambda/src/api/getFiles/index.js +++ b/packages/lambda/src/api/getFiles/index.js @@ -20,16 +20,13 @@ const Request = require('./../../aws/request'); exports.handle = function (event, context, callback) { const repository = new FilesRepository(); - const request = new Request(event, context).queryParameters(['uuids']); - const uuids = request.queryParam('uuids', '').split(','); + const request = new Request(event, context).queryParameters(['fileIds']); + const fileIds = request.queryParam('fileIds', '').split(','); request.validate().then(function () { - return repository.batchGet(uuids); + return repository.batchGet(fileIds); }).then(function (files) { - const results = files.map(function (file) { - return file.all(); - }); - callback(null, results); + callback(null, files); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getSponsor/index.js b/packages/lambda/src/api/getSponsor/index.js index 53071369..e999d5fa 100644 --- a/packages/lambda/src/api/getSponsor/index.js +++ b/packages/lambda/src/api/getSponsor/index.js @@ -23,9 +23,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.validate().then(function () { - return repository.get(request.urlParam('sponsor_tier_uuid'), request.urlParam('sponsor_uuid')); + return repository.get(request.urlParam('sponsor_tier_id'), request.urlParam('sponsor_id')); }).then(function (sponsor) { - callback(null, sponsor.all()); + callback(null, sponsor); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getSponsorTier/index.js b/packages/lambda/src/api/getSponsorTier/index.js index 36465376..13d6a90a 100644 --- a/packages/lambda/src/api/getSponsorTier/index.js +++ b/packages/lambda/src/api/getSponsorTier/index.js @@ -23,9 +23,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.validate().then(function () { - return repository.get(request.urlParam('sponsor_tier_uuid')); + return repository.get(request.urlParam('sponsor_tier_id')); }).then(function (sponsorTier) { - callback(null, sponsorTier.all()); + callback(null, sponsorTier); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getSponsorTiers/index.js b/packages/lambda/src/api/getSponsorTiers/index.js index 90d3391c..45e2c70c 100644 --- a/packages/lambda/src/api/getSponsorTiers/index.js +++ b/packages/lambda/src/api/getSponsorTiers/index.js @@ -25,10 +25,7 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return repository.getAll(); }).then(function (sponsorTiers) { - const results = sponsorTiers.map(function (sponsorTier) { - return sponsorTier.all(); - }); - callback(null, results); + callback(null, sponsorTiers); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getSponsors/index.js b/packages/lambda/src/api/getSponsors/index.js index e38ea5c2..d9562563 100644 --- a/packages/lambda/src/api/getSponsors/index.js +++ b/packages/lambda/src/api/getSponsors/index.js @@ -23,12 +23,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.validate().then(function () { - return repository.getAll(request.urlParam('sponsor_tier_uuid')); + return repository.getAll(request.urlParam('sponsor_tier_id')); }).then(function (sponsors) { - const results = sponsors.map(function (sponsor) { - return sponsor.all(); - }); - callback(null, results); + callback(null, sponsors); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/patchSponsor/index.js b/packages/lambda/src/api/patchSponsor/index.js index 00aba9f8..0ccd5e23 100644 --- a/packages/lambda/src/api/patchSponsor/index.js +++ b/packages/lambda/src/api/patchSponsor/index.js @@ -28,13 +28,13 @@ exports.handle = function (event, context, callback) { let sponsor = null; request.validate().then(function () { - return repository.get(request.urlParam('sponsor_tier_uuid'), request.urlParam('sponsor_uuid')); + return repository.get(request.urlParam('sponsor_tier_id'), request.urlParam('sponsor_id')); }).then(function (result) { sponsor = new Sponsor(result); sponsor.populate(request._body); return sponsor.validate(); }).then(function () { - return repository.save(request.urlParam('sponsor_tier_uuid'), sponsor); + return repository.save(request.urlParam('sponsor_tier_id'), sponsor); }).then(function (response) { sponsor = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/api/patchSponsorTier/index.js b/packages/lambda/src/api/patchSponsorTier/index.js index 6fdef97a..5d3073c0 100644 --- a/packages/lambda/src/api/patchSponsorTier/index.js +++ b/packages/lambda/src/api/patchSponsorTier/index.js @@ -28,7 +28,7 @@ exports.handle = function (event, context, callback) { let sponsorTier = null; request.validate().then(function () { - return repository.get(request.urlParam('sponsor_tier_uuid')); + return repository.get(request.urlParam('sponsor_tier_id')); }).then(function (result) { sponsorTier = new SponsorTier(result); sponsorTier.populate(request._body); diff --git a/packages/lambda/src/api/patchSponsors/index.js b/packages/lambda/src/api/patchSponsors/index.js index 3d4da37d..ff97fe9f 100644 --- a/packages/lambda/src/api/patchSponsors/index.js +++ b/packages/lambda/src/api/patchSponsors/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); @@ -28,19 +27,23 @@ exports.handle = function (event, context, callback) { let sponsors = []; request.validate().then(function () { - request.get('sponsors', []).forEach(function (data) { - sponsors.push(new Sponsor(data)); + let promise = Promise.resolve(); + request.get('sponsors', []).map(function (sponsor) { + promise = promise.then(function () { + return repository.populate(sponsor); + }).then(function (model) { + sponsors.push(model); + }); }); + return promise; }).then(function () { let promise = Promise.resolve(); sponsors.forEach(function (sponsor) { promise = promise.then(function () { - return sponsor.validate(); + return repository.upsert(sponsor, {}); }); }); return promise; - }).then(function () { - return repository.batchSave(request.urlParam('sponsor_tier_uuid'), sponsors); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/postFile/index.js b/packages/lambda/src/api/postFile/index.js index bf4656d5..faa2934b 100644 --- a/packages/lambda/src/api/postFile/index.js +++ b/packages/lambda/src/api/postFile/index.js @@ -14,36 +14,36 @@ * limitations under the License. */ -const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); const S3 = require('./../../aws/s3'); const UserGroupMiddleware = require('./../../middleware/userGroup'); +const UUID = require('node-uuid'); exports.handle = function (event, context, callback) { const lambda = new Lambda(); const repository = new FilesRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin', 'Nonprofit'])).parameters(['content_type', 'filename']); const s3 = new S3(); + const uuid = UUID.v4(); let file = null; request.validate().then(function () { - file = new File({filename: request.get('filename')}); - file.populate({path: `uploads/${file.uuid}`}); - return file.validate(); - }).then(function () { - return repository.save(file); + return repository.populate({filename: request.get('filename')}) + }).then(function (file) { + file.set('path', 'uploads/' + uuid); + return repository.upsert(file, {}); }).then(function (model) { - file = model; + file = model[0]; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - return s3.getSignedUrl(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, file.path, request.get('content_type'), 'public-read'); + return s3.getSignedUrl(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, file.get('path'), request.get('content_type'), 'public-read'); }).then(function (url) { callback(null, { upload_url: url, - file: file.all() + file: file }); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); diff --git a/packages/lambda/src/api/postSponsor/index.js b/packages/lambda/src/api/postSponsor/index.js index 35541b53..b902c59c 100644 --- a/packages/lambda/src/api/postSponsor/index.js +++ b/packages/lambda/src/api/postSponsor/index.js @@ -26,20 +26,22 @@ exports.handle = function (event, context, callback) { const repository = new SponsorsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let sponsor = new Sponsor({sponsorTierUuid: request.urlParam('sponsor_tier_uuid')}); + let sponsor; request.validate().then(function () { - sponsor.populate(request._body); - return repository.getCount(request.urlParam('sponsor_tier_uuid')); + return repository.populate(request._body) + }).then(function (model) { + sponsor = model; + return repository.getCount(request.urlParam('sponsor_tier_id')); }).then(function (count) { - sponsor.populate({sortOrder: count}); + sponsor.set('sortOrder', count); return sponsor.validate(); - }).then(function () { - return repository.save(request.urlParam('sponsor_tier_uuid'), sponsor); + }).then(function (sponsor) { + return repository.save(request.urlParam('sponsor_tier_id'), sponsor); }).then(function (response) { sponsor = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - callback(null, sponsor.all()); + callback(null, sponsor); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/postSponsorTier/index.js b/packages/lambda/src/api/postSponsorTier/index.js index af716e2f..a9d946b7 100644 --- a/packages/lambda/src/api/postSponsorTier/index.js +++ b/packages/lambda/src/api/postSponsorTier/index.js @@ -26,19 +26,22 @@ exports.handle = function (event, context, callback) { const repository = new SponsorTiersRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); - let sponsorTier = new SponsorTier(request._body); + let sponsorTier; request.validate().then(function () { + return repository.populate(request._body) + }).then(function (model) { + sponsorTier = model; return repository.getCount(); }).then(function (count) { - sponsorTier.populate({sortOrder: count}); + sponsorTier.set('sortOrder', count); return sponsorTier.validate(); - }).then(function () { - return repository.save(sponsorTier); + }).then(function (sponsorTier) { + return repository.upsert(sponsorTier, {}); }).then(function (response) { sponsorTier = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - callback(null, sponsorTier.all()); + callback(null, sponsorTier); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index 9d530511..d955b003 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -49,7 +49,7 @@ exports.handle = function (event, context, callback) { }); promise = promise.then(function() { - return repository.bulkInsert('Settings', bulkData); + return repository.bulkCreate(bulkData); }); promise = promise.then(function () { diff --git a/packages/lambda/src/models/file.js b/packages/lambda/src/models/file.js new file mode 100644 index 00000000..9152f777 --- /dev/null +++ b/packages/lambda/src/models/file.js @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const {DataTypes} = require('sequelize'); + +module.exports = (sequelize) => { + return sequelize.define('File', { + path: { + type: DataTypes.STRING, + allowNull: false, + }, + filename: { + type: DataTypes.STRING, + allowNull: false, + }, + }); +}; \ No newline at end of file diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js index fc4021d2..998a4df2 100644 --- a/packages/lambda/src/models/index.js +++ b/packages/lambda/src/models/index.js @@ -27,6 +27,12 @@ module.exports = function() { models[model.name] = model; model = require('./content')(sequelize); models[model.name] = model; + model = require('./sponsorTier')(sequelize); + models[model.name] = model; + model = require('./sponsor')(sequelize); + models[model.name] = model; + model = require('./file')(sequelize); + models[model.name] = model; return models; }); } diff --git a/packages/lambda/src/models/sponsor.js b/packages/lambda/src/models/sponsor.js new file mode 100644 index 00000000..76aa3096 --- /dev/null +++ b/packages/lambda/src/models/sponsor.js @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Sponsor = sequelize.define('Sponsor', { + logoUrl: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "" + }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + sortOrder: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + url: { + type: DataTypes.STRING, + allowNull: false, + }, + fileId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + sponsorTierId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + }); + + Sponsor.associate = function (models) { + Sponsor.hasOne(models.SponsorTier, { + foreignKey: 'sponsorTierId' + }); + }; + + return Sponsor; +}; \ No newline at end of file diff --git a/packages/lambda/src/models/sponsorTier.js b/packages/lambda/src/models/sponsorTier.js new file mode 100644 index 00000000..e5a446a3 --- /dev/null +++ b/packages/lambda/src/models/sponsorTier.js @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Firespring, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const {DataTypes} = require('sequelize'); + +module.exports = (sequelize) => { + const SponsorTier = sequelize.define('SponsorTier', { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + size: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isIn: [['LARGE', 'DEFAULT', 'SMALL']] + } + }, + sortOrder: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + }); + + SponsorTier.associate = function (models) { + SponsorTier.hasMany(models.Sponsor, { + foreignKey: 'sponsorTierId' + }); + }; + + return SponsorTier; +}; \ No newline at end of file diff --git a/packages/lambda/src/repositories/files.js b/packages/lambda/src/repositories/files.js index 72eff845..28e6af29 100644 --- a/packages/lambda/src/repositories/files.js +++ b/packages/lambda/src/repositories/files.js @@ -18,6 +18,8 @@ const File = require('./../dynamo-models/file'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); +const loadModels = require('./../models/index'); +const Sequelize = require('sequelize'); /** * FilesRepository constructor @@ -39,22 +41,48 @@ function FilesRepository(options) { */ FilesRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +FilesRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.File(data); + }).finally(function () { + return allModels.sequelize.close(); + }) +}; + /** * Get a File * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -FilesRepository.prototype.get = function (uuid) { - const repository = this; +FilesRepository.prototype.get = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.getByKey('uuid', uuid).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new File(data.Item)); - } - reject(new ResourceNotFoundException('The specified file does not exist.')); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.File.findOne({ + where: { + id: id + } + }).then(function (setting) { + if (setting instanceof allModels.File) { + resolve(setting); + } + reject(new ResourceNotFoundException('The specified file does not exist.')); + }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -82,29 +110,30 @@ FilesRepository.prototype.getAll = function () { }; /** - * Get Files by uuids + * Get Files by id * - * @param {[]} uuids + * @param {[]} fileIds * @return {Promise} */ -FilesRepository.prototype.batchGet = function (uuids) { - const repository = this; +FilesRepository.prototype.batchGet = function (fileIds) { + let allModels; return new Promise(function (resolve, reject) { - if (!uuids) { - reject(new Error('uuids is undefined')); - } - const map = []; - uuids.forEach(function (value) { - map.push({uuid: value}); - }); - repository.batchGetKeys(map).then(function (data) { - let results = []; - data.forEach(function (item) { - results.push(new File(item)); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.File.findAll({ + where: { + id: { + [Sequelize.Op.or]: fileIds + } + } }); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -132,22 +161,49 @@ FilesRepository.prototype.delete = function (uuid) { * @param {File} model */ FilesRepository.prototype.save = function (model) { + let allModels; const repository = this; return new Promise(function (resolve, reject) { - if (!(model instanceof File)) { - reject(new Error('invalid File model')); - } - model.validate().then(function () { - const key = { - uuid: model.uuid - }; - repository.put(key, model.except(['uuid'])).then(function (data) { - resolve(new File(data.Attributes)); - }).catch(function (err) { - reject(err); + return loadModels().then(function (models) { + allModels = models; + if (!(model instanceof allModels.File)) { + reject(new Error('invalid File model')); + } + return repository.upsert(model, {}); + }).then(function (file) { + resolve(file); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param model + * @param data + * @return {Promise} + */ +FilesRepository.prototype.upsert = function (model, data) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.File.upsert({ + 'id': model.get('id'), + 'path': typeof data.path !== "undefined" ? data.path : model.get('path'), + 'filename': typeof data.filename !== "undefined" ? data.filename : model.get('filename'), }); + }).then(function (file) { + resolve(file); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index b4a3f0e2..56832e51 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -251,16 +251,6 @@ Repository.prototype.batchWrite = function (requestItems, retries) { }); }; -Repository.prototype.bulkInsert = function (tableName, data) { - let allModels; - return loadModels().then(function (models) { - allModels = models; - return models.bulkInsert(tableName, data); - }).finally(function () { - return allModels.sequelize.close(); - }); -}; - /** * Batch update models * @@ -268,24 +258,24 @@ Repository.prototype.bulkInsert = function (tableName, data) { * @return {Promise} */ Repository.prototype.batchUpdate = function (models) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const requestItems = []; - models = models || []; - models.forEach(function (model) { - if (model instanceof Model) { - model.beforeSave(); - requestItems.push({ - PutRequest: { - Item: model.nonEmpty() - } - }); - } - }); - repository.batchWrite(requestItems, 3).then(function (data) { - resolve(data); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.update(); + }) + }); + return promise; + }).then(function (stuff) { + resolve(stuff); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -297,23 +287,24 @@ Repository.prototype.batchUpdate = function (models) { * @return {Promise} */ Repository.prototype.batchDelete = function (models) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const requestItems = []; - models = models || []; - models.forEach(function (model) { - requestItems.push({ - DeleteRequest: { - Key: { - uuid: model.uuid - } - } + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.destroy(); + }) }); - }); - repository.batchWrite(requestItems, 3).then(function (data) { - resolve(data); + return promise; + }).then(function (stuff) { + resolve(stuff); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 0a98fba6..d7f4c01a 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -192,6 +192,28 @@ SettingsRepository.prototype.batchDeleteByKey = function (models) { }); }; +/** + * Bulk create used in initial start up + * + * @param {[]} data + * @return {Promise} + */ +SettingsRepository.prototype.bulkCreate = function (data) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + return models.Setting.bulkCreate(data); + }).then(function (setting) { + resolve(setting); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + /** * Create or update a Setting * @@ -207,8 +229,8 @@ SettingsRepository.prototype.save = function (model) { reject(new Error('invalid Setting model')); } return repository.upsert(model, {}); - }).then(function (content) { - resolve(content); + }).then(function (setting) { + resolve(setting); }).catch(function (err) { reject(err); }).finally(function () { diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index 8931e79d..ce3cd332 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -14,11 +14,11 @@ * limitations under the License. */ -const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); const SponsorTier = require('./../dynamo-models/sponsorTier'); +const loadModels = require('../models/index'); /** * SponsorTiersRepository constructor @@ -40,22 +40,48 @@ function SponsorTiersRepository(options) { */ SponsorTiersRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +SponsorTiersRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.SponsorTier(data); + }).finally(function () { + return allModels.sequelize.close(); + }) +}; + /** * Get a Sponsor Tier * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -SponsorTiersRepository.prototype.get = function (uuid) { - const repository = this; +SponsorTiersRepository.prototype.get = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.getByKey('uuid', uuid).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new SponsorTier(data.Item)); - } - reject(new ResourceNotFoundException('The specified sponsor tier does not exist.')); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.SponsorTier.findOne({ + where: { + id: id + } + }).then(function (sponsorTier) { + if (sponsorTier instanceof allModels.SponsorTier) { + resolve(sponsorTier); + } + reject(new ResourceNotFoundException('The specified sponsorTier does not exist.')); + }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -66,18 +92,18 @@ SponsorTiersRepository.prototype.get = function (uuid) { * @return {Promise} */ SponsorTiersRepository.prototype.getAll = function () { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - repository.batchScan().then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new SponsorTier(item)); - }); - } + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.SponsorTier.findAll(); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -88,14 +114,18 @@ SponsorTiersRepository.prototype.getAll = function () { * @return {Promise} */ SponsorTiersRepository.prototype.getCount = function () { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const builder = new QueryBuilder('scan'); - builder.select('COUNT'); - repository.batchQuery(builder).then(function (data) { - resolve(data.Count); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.SponsorTier.count(); + }).then(function (result) { + resolve(result); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -103,16 +133,22 @@ SponsorTiersRepository.prototype.getCount = function () { /** * Delete a Sponsor Tier * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -SponsorTiersRepository.prototype.delete = function (uuid) { - const repository = this; +SponsorTiersRepository.prototype.delete = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.deleteByKey('uuid', uuid).then(function () { - resolve(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Setting.destroy({where: {id: id}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -123,22 +159,50 @@ SponsorTiersRepository.prototype.delete = function (uuid) { * @param {SponsorTier} model */ SponsorTiersRepository.prototype.save = function (model) { + let allModels; const repository = this; return new Promise(function (resolve, reject) { - if (!(model instanceof SponsorTier)) { - reject(new Error('invalid SponsorTier model')); - } - model.validate().then(function () { - const key = { - uuid: model.uuid - }; - repository.put(key, model.except(['uuid'])).then(function (data) { - resolve(new SponsorTier(data.Attributes)); - }).catch(function (err) { - reject(err); + return loadModels().then(function (models) { + allModels = models; + if (!(model instanceof allModels.SponsorTier)) { + reject(new Error('invalid SponsorTier model')); + } + return repository.upsert(model, {}); + }).then(function (sponsorTier) { + resolve(sponsorTier); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param model + * @param data + * @return {Promise} + */ +SponsorTiersRepository.prototype.upsert = function (model, data) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.SponsorTier.upsert({ + 'id': model.get('id'), + 'name': typeof data.name !== "undefined" ? data.name : model.get('name'), + 'size': typeof data.size !== "undefined" ? data.size : model.get('size'), + 'sortOrder': typeof data.sortOrder !== "undefined" ? data.sortOrder : model.get('sortOrder'), }); + }).then(function (sponsorTier) { + resolve(sponsorTier); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 697f5b56..9c2b8f78 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -20,6 +20,7 @@ const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); const Sponsor = require('./../dynamo-models/sponsor'); const SponsorTiersRepository = require('./sponsorTiers'); +const loadModels = require('../models/index'); /** * SponsorsRepository constructor @@ -41,30 +42,50 @@ function SponsorsRepository(options) { */ SponsorsRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +SponsorsRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.Sponsor(data); + }).finally(function () { + return allModels.sequelize.close(); + }) +}; + /** * Get a Sponsor * - * @param {String} sponsorTierUuid - * @param {String} uuid + * @param {String} sponsorTierId + * @param {String} id * @return {Promise} */ -SponsorsRepository.prototype.get = function (sponsorTierUuid, uuid) { - const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); +SponsorsRepository.prototype.get = function (sponsorTierId, id) { + let allModels; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - const builder = new QueryBuilder('query'); - builder.condition('uuid', '=', uuid).filter('sponsorTierUuid', '=', sponsorTierUuid); - repository.batchQuery(builder).then(function (data) { - if (data.Items.length === 1) { - resolve(new Sponsor(data.Items[0])); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.findOne({ + where: { + id: id, + sponsorTierId: sponsorTierId + } + }).then(function (sponsor) { + if (sponsor instanceof allModels.Sponsor) { + resolve(sponsor); } reject(new ResourceNotFoundException('The specified sponsor does not exist.')); - }).catch(function (err) { - reject(err); }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -72,29 +93,26 @@ SponsorsRepository.prototype.get = function (sponsorTierUuid, uuid) { /** * Get all Sponsors for this Sponsor Tier * - * @param {String} sponsorTierUuid + * @param {String} sponsorTierId * @return {Promise} */ -SponsorsRepository.prototype.getAll = function (sponsorTierUuid) { - const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); +SponsorsRepository.prototype.getAll = function (sponsorTierId) { + let allModels; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - const builder = new QueryBuilder('query'); - builder.index('sponsorTierUuidIndex').condition('sponsorTierUuid', '=', sponsorTierUuid); - repository.batchQuery(builder).then(function (data) { - const results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new Sponsor(item)); - }); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.findAll({ + where: { + sponsorTierId: sponsorTierId } - resolve(results); - }).catch(function (err) { - reject(err); }); + }).then(function (results) { + resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -102,23 +120,26 @@ SponsorsRepository.prototype.getAll = function (sponsorTierUuid) { /** * Get a count of all Sponsors for a SponsorTier * - * @param {String} sponsorTierUuid + * @param {String} sponsorTierId * @return {Promise} */ -SponsorsRepository.prototype.getCount = function (sponsorTierUuid) { - const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); +SponsorsRepository.prototype.getCount = function (sponsorTierId) { + let allModels; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - const builder = new QueryBuilder('query'); - builder.index('sponsorTierUuidIndex').condition('sponsorTierUuid', '=', sponsorTierUuid).select('COUNT'); - repository.batchQuery(builder).then(function (data) { - resolve(data.Count); - }).catch(function (err) { - reject(err); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.count({ + where: { + sponsorTierId: sponsorTierId + } }); + }).then(function (result) { + resolve(result); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -126,54 +147,58 @@ SponsorsRepository.prototype.getCount = function (sponsorTierUuid) { /** * Delete a Sponsor * - * @param {String} sponsorTierUuid - * @param {String} uuid + * @param {String} sponsorTierId + * @param {String} id * @return {Promise} */ -SponsorsRepository.prototype.delete = function (sponsorTierUuid, uuid) { - const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); +SponsorsRepository.prototype.delete = function (sponsorTierId, id) { + let allModels; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - repository.deleteByKey('uuid', uuid).then(function () { - resolve(); - }).catch(function (err) { - reject(err); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.destroy({ + where: + { + sponsorTierId: sponsorTierId, + id: id + } }); + }).then(function () { + resolve() }).catch(function (err) { reject(err); - }) + }).finally(function () { + return allModels.sequelize.close(); + }); }); }; /** * Create or update a Donation Tier * - * @param {String} sponsorTierUuid + * @param {String} sponsorTierId * @param {Sponsor} model */ -SponsorsRepository.prototype.save = function (sponsorTierUuid, model) { +SponsorsRepository.prototype.save = function (sponsorTierId, model) { + let allModels; const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); + const sponsorTierRepository = new SponsorTiersRepository(); return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - if (!(model instanceof Sponsor)) { - reject(new Error('invalid Sponsor model')); + return loadModels().then(function (models) { + allModels = models; + return sponsorTierRepository.get(sponsorTierId); + }).then(function (sponsorTier) { + if (!sponsorTier instanceof allModels.SponsorTier) { + reject('SponsorTier does not exist!'); } - model.validate().then(function () { - const key = { - uuid: model.uuid - }; - repository.put(key, model.except(['uuid'])).then(function (data) { - resolve(new Sponsor(data.Attributes)); - }).catch(function (err) { - reject(err); - }); - }).catch(function (err) { - reject(err); - }); + return repository.upsert(model, {}, sponsorTierId); + }).then(function (sponsor) { + resolve(sponsor); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -181,16 +206,22 @@ SponsorsRepository.prototype.save = function (sponsorTierUuid, model) { /** * Batch create or update Sponsors * - * @param {string} sponsorTierUuid + * @param {string} sponsorTierId * @param {[]} models * @return {Promise} */ -SponsorsRepository.prototype.batchSave = function (sponsorTierUuid, models) { - const repository = this; +SponsorsRepository.prototype.batchSave = function (sponsorTierId, models) { const sponsorTiersRepository = new SponsorTiersRepository(); + const repository = this; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - return repository.batchUpdate(models); + sponsorTiersRepository.get(sponsorTierId).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return repository.upsert(model, {}) + }) + }); + return promise; }).then(function () { resolve(); }).catch(function (err) { @@ -202,20 +233,62 @@ SponsorsRepository.prototype.batchSave = function (sponsorTierUuid, models) { /** * Batch delete Sponsors * - * @param {string} sponsorTierUuid + * @param {string} sponsorTierId * @param {[]} models * @return {Promise} */ -SponsorsRepository.prototype.batchRemove = function (sponsorTierUuid, models) { - const repository = this; - const sponsorTiersRepository = new SponsorTiersRepository(); +SponsorsRepository.prototype.batchRemove = function (sponsorTierId, models) { + let allModels; return new Promise(function (resolve, reject) { - sponsorTiersRepository.get(sponsorTierUuid).then(function () { - return repository.batchDelete(models); + return loadModels().then(function (models) { + allModels = models; }).then(function () { - resolve(); + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.destroy(); + }) + }); + return promise; + }).then(function (stuff) { + resolve(stuff); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param sponsorTierId + * @param model + * @param data + * @return {Promise} + */ +SponsorsRepository.prototype.upsert = function (model, data, sponsorTierId) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.upsert({ + 'id': model.get('id'), + 'name': typeof data.name !== "undefined" ? data.name : model.get('name'), + 'url': typeof data.url !== "undefined" ? data.url : model.get('url'), + 'sortOrder': typeof data.sortOrder !== "undefined" ? data.sortOrder : model.get('sortOrder'), + 'fileId': typeof data.fileId !== "undefined" ? data.fileId : model.get('fileId'), + 'logoUrl': typeof data.logoUrl !== "undefined" ? data.logoUrl : model.get('logoUrl'), + 'sponsorTierId': sponsorTierId + }); + }).then(function (sponsor) { + resolve(sponsor); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; From 979fff2819831a26d5b2810b0311258dcecce96c Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 1 Sep 2020 17:07:39 -0500 Subject: [PATCH 056/140] GD-1645: Update Sponsors Repository --- packages/lambda/src/api/deleteSponsors/index.js | 9 +++++++-- packages/lambda/src/api/patchSponsor/index.js | 9 ++------- packages/lambda/src/api/patchSponsorTier/index.js | 9 ++------- packages/lambda/src/api/patchSponsorTiers/index.js | 11 ++++------- packages/lambda/src/api/postSponsor/index.js | 1 - packages/lambda/src/api/postSponsorTier/index.js | 1 - packages/lambda/src/repositories/sponsorTiers.js | 1 - packages/lambda/src/repositories/sponsors.js | 2 -- 8 files changed, 15 insertions(+), 28 deletions(-) diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index ec2c0f64..5779f601 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); @@ -28,9 +27,15 @@ exports.handle = function (event, context, callback) { let sponsors = []; request.validate().then(function () { + let promise = Promise.resolve(); request.get('sponsors', []).forEach(function (data) { - sponsors.push(new Sponsor(data)); + promise = promise.then(function () { + return repository.populate(data); + }).then(function (sponsor) { + sponsors.push(sponsor); + }); }); + return promise; }).then(function () { return repository.batchRemove(request.urlParam('sponsor_tier_id'), sponsors); }).then(function () { diff --git a/packages/lambda/src/api/patchSponsor/index.js b/packages/lambda/src/api/patchSponsor/index.js index 0ccd5e23..4d49b203 100644 --- a/packages/lambda/src/api/patchSponsor/index.js +++ b/packages/lambda/src/api/patchSponsor/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); @@ -29,12 +28,8 @@ exports.handle = function (event, context, callback) { let sponsor = null; request.validate().then(function () { return repository.get(request.urlParam('sponsor_tier_id'), request.urlParam('sponsor_id')); - }).then(function (result) { - sponsor = new Sponsor(result); - sponsor.populate(request._body); - return sponsor.validate(); - }).then(function () { - return repository.save(request.urlParam('sponsor_tier_id'), sponsor); + }).then(function (sponsor) { + return repository.upsert(sponsor, request._body); }).then(function (response) { sponsor = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/api/patchSponsorTier/index.js b/packages/lambda/src/api/patchSponsorTier/index.js index 5d3073c0..eb5ccbff 100644 --- a/packages/lambda/src/api/patchSponsorTier/index.js +++ b/packages/lambda/src/api/patchSponsorTier/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); @@ -29,12 +28,8 @@ exports.handle = function (event, context, callback) { let sponsorTier = null; request.validate().then(function () { return repository.get(request.urlParam('sponsor_tier_id')); - }).then(function (result) { - sponsorTier = new SponsorTier(result); - sponsorTier.populate(request._body); - return sponsorTier.validate(); - }).then(function () { - return repository.save(sponsorTier); + }).then(function (sponsorTier) { + return repository.upsert(sponsorTier, request._body); }).then(function (response) { sponsorTier = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/api/patchSponsorTiers/index.js b/packages/lambda/src/api/patchSponsorTiers/index.js index b8be51b5..7c892c96 100644 --- a/packages/lambda/src/api/patchSponsorTiers/index.js +++ b/packages/lambda/src/api/patchSponsorTiers/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); @@ -28,14 +27,12 @@ exports.handle = function (event, context, callback) { let sponsorTiers = []; request.validate().then(function () { - request.get('sponsorTiers', []).forEach(function (data) { - sponsorTiers.push(new SponsorTier(data)); - }); - }).then(function () { let promise = Promise.resolve(); - sponsorTiers.forEach(function (sponsorTier) { + request.get('sponsorTiers', []).forEach(function (data) { promise = promise.then(function () { - return sponsorTier.validate(); + return repository.populate(data); + }).then(function (sponsorTier) { + sponsorTiers.push(sponsorTier); }); }); return promise; diff --git a/packages/lambda/src/api/postSponsor/index.js b/packages/lambda/src/api/postSponsor/index.js index b902c59c..14dc4341 100644 --- a/packages/lambda/src/api/postSponsor/index.js +++ b/packages/lambda/src/api/postSponsor/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const Sponsor = require('./../../dynamo-models/sponsor'); const SponsorsRepository = require('./../../repositories/sponsors'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/api/postSponsorTier/index.js b/packages/lambda/src/api/postSponsorTier/index.js index a9d946b7..35e4e23c 100644 --- a/packages/lambda/src/api/postSponsorTier/index.js +++ b/packages/lambda/src/api/postSponsorTier/index.js @@ -17,7 +17,6 @@ const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); const Request = require('./../../aws/request'); -const SponsorTier = require('./../../dynamo-models/sponsorTier'); const SponsorTiersRepository = require('./../../repositories/sponsorTiers'); const UserGroupMiddleware = require('./../../middleware/userGroup'); diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index ce3cd332..a885a1b5 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -17,7 +17,6 @@ const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const SponsorTier = require('./../dynamo-models/sponsorTier'); const loadModels = require('../models/index'); /** diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 9c2b8f78..28a29cd2 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -14,11 +14,9 @@ * limitations under the License. */ -const QueryBuilder = require('./../aws/queryBuilder'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); -const Sponsor = require('./../dynamo-models/sponsor'); const SponsorTiersRepository = require('./sponsorTiers'); const loadModels = require('../models/index'); From bd79d049b1b758bf3811fcb6fae5c3b2e31b8d68 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 2 Sep 2020 08:23:55 -0500 Subject: [PATCH 057/140] GD-1643: Update contents repo --- packages/lambda/src/api/patchContent/index.js | 9 ++------- packages/lambda/src/api/postContent/index.js | 1 - packages/lambda/src/repositories/contents.js | 3 +-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/lambda/src/api/patchContent/index.js b/packages/lambda/src/api/patchContent/index.js index f8356ff0..688e0195 100644 --- a/packages/lambda/src/api/patchContent/index.js +++ b/packages/lambda/src/api/patchContent/index.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); @@ -30,16 +29,12 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return repository.get(request.urlParam('content_id')); }).then(function (result) { - content = new Content(result); - content.populate(request._body); - return content.validate(); - }).then(function () { - return repository.save(content); + return repository.upsert(result, request._body); }).then(function (response) { content = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - callback(null, content.all()); + callback(null, content); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/postContent/index.js b/packages/lambda/src/api/postContent/index.js index eef702ac..111e99d3 100644 --- a/packages/lambda/src/api/postContent/index.js +++ b/packages/lambda/src/api/postContent/index.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const Content = require('./../../dynamo-models/content'); const ContentsRepository = require('./../../repositories/contents'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index 141dcd7d..4e01c385 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const Content = require('./../dynamo-models/content'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); @@ -298,7 +297,7 @@ ContentsRepository.prototype.batchDeleteByKey = function (key) { /** * Create or update a Content * - * @param {Content} model + * @param {Promise} model */ ContentsRepository.prototype.save = function (model) { let allModels; From 38214c57a3c9ca5ce1d6b93e8d5d480bbd07dd27 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 2 Sep 2020 14:55:08 -0500 Subject: [PATCH 058/140] WIP --- .../templates/givesource-api-nonprofits.yml | 4 +- .../templates/givesource-api-users.yml | 47 ++++++++++++++-- .../cloudformation/templates/givesource.yml | 1 + packages/lambda/migrations/00_initial.js | 56 ++++++++++++++++++- .../src/api/deleteNonprofitUser/index.js | 4 +- packages/lambda/src/api/deleteUser/index.js | 4 +- packages/lambda/src/api/patchUser/index.js | 4 +- .../api/resendUserEmailVerification/index.js | 2 +- 8 files changed, 108 insertions(+), 14 deletions(-) diff --git a/packages/cloudformation/templates/givesource-api-nonprofits.yml b/packages/cloudformation/templates/givesource-api-nonprofits.yml index c6a3e7df..9fc0d7f0 100644 --- a/packages/cloudformation/templates/givesource-api-nonprofits.yml +++ b/packages/cloudformation/templates/givesource-api-nonprofits.yml @@ -835,7 +835,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/users/{user_id} DependsOn: DeleteNonprofitUserLambdaFunction # Nonprofit Admin Lambda Resources @@ -3153,7 +3153,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitUsersApiResource - PathPart: "{user_uuid}" + PathPart: "{user_id}" GetNonprofitUsersApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource-api-users.yml b/packages/cloudformation/templates/givesource-api-users.yml index 3168ff49..eeee582b 100644 --- a/packages/cloudformation/templates/givesource-api-users.yml +++ b/packages/cloudformation/templates/givesource-api-users.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -55,6 +58,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetUserProfileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -87,6 +96,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetUsersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -117,6 +132,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -146,6 +167,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -154,7 +181,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/users/{user_id} DependsOn: PatchUserLambdaFunction DeleteUserLambdaFunction: @@ -176,6 +203,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -184,7 +217,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/users/{user_id} DependsOn: DeleteUserLambdaFunction # Resend User Email Verification Lambda Resources @@ -208,6 +241,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet ResendUserEmailVerificationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -216,7 +255,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/users/{user_uuid}/resend-verification-email + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/users/{user_id}/resend-verification-email DependsOn: ResendUserEmailVerificationLambdaFunction # User Profile Api Gateway Resources @@ -342,7 +381,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref UsersApiResource - PathPart: "{user_uuid}" + PathPart: "{user_id}" GetUsersApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 93e45c02..671c103f 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -684,6 +684,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index 7063da5b..a83a1d73 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -763,6 +763,57 @@ module.exports = { allowNull: false, defaultValue: '0000-00-00 00:00:00' } + }), + queryInterface.createTable('Users', { + id: { + type: Sequelize.INTEGER(11), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + email: { + type: Sequelize.STRING(2048), + allowNull: false, + }, + firstName: { + type: Sequelize.STRING(2048), + allowNull: false, + defaultValue: '' + }, + lastName: { + type: Sequelize.STRING(2048), + allowNull: false, + defaultValue: '' + }, + isVerified: { + type: Sequelize.BOOLEAN, + allowNull: false, + }, + nonprofitId: { + type: Sequelize.INTEGER(11), + allowNull: false, + defaultValue: 0, + }, + cognitoUuid: { + type: Sequelize.STRING(2048), + allowNull: false, + defaultValue: '' + }, + isDeleted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: '0000-00-00 00:00:00' + } }) ]); @@ -778,6 +829,8 @@ module.exports = { queryInterface.addIndex('NonprofitSlides', ['nonprofitId']), queryInterface.addIndex('Sponsors', ['sponsorTierId']), queryInterface.addIndex('SponsorTiers', ['name']), + queryInterface.addIndex('Users', ['email']), + queryInterface.addIndex('Users', ['cognitoUuid']), ]); }, down: async (queryInterface, Sequelize) => { @@ -795,7 +848,8 @@ module.exports = { queryInterface.dropTable('Reports'), queryInterface.dropTable('Settings'), queryInterface.dropTable('Sponsors'), - queryInterface.dropTable('SponsorTiers') + queryInterface.dropTable('SponsorTiers'), + queryInterface.dropTable('Users') ]); } }; diff --git a/packages/lambda/src/api/deleteNonprofitUser/index.js b/packages/lambda/src/api/deleteNonprofitUser/index.js index 15a0bff4..bfc786d3 100644 --- a/packages/lambda/src/api/deleteNonprofitUser/index.js +++ b/packages/lambda/src/api/deleteNonprofitUser/index.js @@ -27,9 +27,9 @@ exports.handle = function (event, context, callback) { request.middleware(new NonprofitResourceMiddleware(request.urlParam('nonprofit_uuid'), ['SuperAdmin', 'Admin'])); request.validate().then(function () { - return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, request.urlParam('user_uuid')); + return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, request.urlParam('user_id')); }).then(function () { - return repository.delete(request.urlParam('user_uuid')); + return repository.delete(request.urlParam('user_id')); }).then(function () { callback(); }).catch(function (err) { diff --git a/packages/lambda/src/api/deleteUser/index.js b/packages/lambda/src/api/deleteUser/index.js index 92aff74d..24bd542f 100644 --- a/packages/lambda/src/api/deleteUser/index.js +++ b/packages/lambda/src/api/deleteUser/index.js @@ -26,9 +26,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); request.validate().then(function () { - return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, request.urlParam('user_uuid')); + return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, request.urlParam('user_id')); }).then(function () { - return repository.delete(request.urlParam('user_uuid')); + return repository.delete(request.urlParam('user_id')); }).then(function () { callback(); }).catch(function (err) { diff --git a/packages/lambda/src/api/patchUser/index.js b/packages/lambda/src/api/patchUser/index.js index c5f15d65..12688672 100644 --- a/packages/lambda/src/api/patchUser/index.js +++ b/packages/lambda/src/api/patchUser/index.js @@ -23,11 +23,11 @@ const UsersRepository = require('./../../repositories/users'); exports.handle = function (event, context, callback) { const repository = new UsersRepository(); const request = new Request(event, context); - request.middleware(new UserResourceMiddleware(request.urlParam('user_uuid'))); + request.middleware(new UserResourceMiddleware(request.urlParam('user_id'))); let user = null; request.validate().then(function () { - return repository.get(request.urlParam('user_uuid')); + return repository.get(request.urlParam('user_id')); }).then(function (result) { user = new User(result); user.populate(request._body); diff --git a/packages/lambda/src/api/resendUserEmailVerification/index.js b/packages/lambda/src/api/resendUserEmailVerification/index.js index 9eae74cd..0a7c5d19 100644 --- a/packages/lambda/src/api/resendUserEmailVerification/index.js +++ b/packages/lambda/src/api/resendUserEmailVerification/index.js @@ -28,7 +28,7 @@ exports.handle = function (event, context, callback) { let user = null; request.validate().then(function () { - return repository.get(request.urlParam('user_uuid')); + return repository.get(request.urlParam('user_id')); }).then(function (result) { user = new User(result); user.populate(request._body); From 53581d5670f86b314b27766d11afddb5d30a03e1 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 3 Sep 2020 08:25:57 -0500 Subject: [PATCH 059/140] 1645 --> 1643 --- .../lambda/src/custom/saveSettings/index.js | 2 +- .../lambda/src/repositories/repository.js | 67 ++++++++----------- packages/lambda/src/repositories/settings.js | 22 ++++++ 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/packages/lambda/src/custom/saveSettings/index.js b/packages/lambda/src/custom/saveSettings/index.js index 9d530511..d955b003 100644 --- a/packages/lambda/src/custom/saveSettings/index.js +++ b/packages/lambda/src/custom/saveSettings/index.js @@ -49,7 +49,7 @@ exports.handle = function (event, context, callback) { }); promise = promise.then(function() { - return repository.bulkInsert('Settings', bulkData); + return repository.bulkCreate(bulkData); }); promise = promise.then(function () { diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index b4a3f0e2..56832e51 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -251,16 +251,6 @@ Repository.prototype.batchWrite = function (requestItems, retries) { }); }; -Repository.prototype.bulkInsert = function (tableName, data) { - let allModels; - return loadModels().then(function (models) { - allModels = models; - return models.bulkInsert(tableName, data); - }).finally(function () { - return allModels.sequelize.close(); - }); -}; - /** * Batch update models * @@ -268,24 +258,24 @@ Repository.prototype.bulkInsert = function (tableName, data) { * @return {Promise} */ Repository.prototype.batchUpdate = function (models) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const requestItems = []; - models = models || []; - models.forEach(function (model) { - if (model instanceof Model) { - model.beforeSave(); - requestItems.push({ - PutRequest: { - Item: model.nonEmpty() - } - }); - } - }); - repository.batchWrite(requestItems, 3).then(function (data) { - resolve(data); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.update(); + }) + }); + return promise; + }).then(function (stuff) { + resolve(stuff); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -297,23 +287,24 @@ Repository.prototype.batchUpdate = function (models) { * @return {Promise} */ Repository.prototype.batchDelete = function (models) { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const requestItems = []; - models = models || []; - models.forEach(function (model) { - requestItems.push({ - DeleteRequest: { - Key: { - uuid: model.uuid - } - } + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + let promise = Promise.resolve(); + promise = promise.then(function () { + models.forEach(function (model) { + return model.destroy(); + }) }); - }); - repository.batchWrite(requestItems, 3).then(function (data) { - resolve(data); + return promise; + }).then(function (stuff) { + resolve(stuff); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index 0a98fba6..7f7787ab 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -192,6 +192,28 @@ SettingsRepository.prototype.batchDeleteByKey = function (models) { }); }; +/** + * Bulk create used in initial start up + * + * @param {[]} data + * @return {Promise} + */ +SettingsRepository.prototype.bulkCreate = function (data) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + return models.Setting.bulkCreate(data); + }).then(function (setting) { + resolve(setting); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + /** * Create or update a Setting * From 1926173b39440e2047e9f8dffe1dec27646d83d9 Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Wed, 2 Sep 2020 16:31:43 -0500 Subject: [PATCH 060/140] WIP --- .../cloudformation/bin/aws/cloudFormation.js | 5 ++- packages/lambda/src/aws/cloudformation.js | 39 ------------------- packages/lambda/src/models/connect.js | 12 ++---- .../lambda/src/repositories/repository.js | 2 +- 4 files changed, 7 insertions(+), 51 deletions(-) delete mode 100644 packages/lambda/src/aws/cloudformation.js diff --git a/packages/cloudformation/bin/aws/cloudFormation.js b/packages/cloudformation/bin/aws/cloudFormation.js index 414ef390..9b6c51e4 100644 --- a/packages/cloudformation/bin/aws/cloudFormation.js +++ b/packages/cloudformation/bin/aws/cloudFormation.js @@ -39,7 +39,8 @@ CloudFormation.prototype.createStack = function (region, stackName, templateUrl, const params = { Capabilities: ['CAPABILITY_IAM'], StackName: stackName, - TemplateURL: templateUrl + TemplateURL: templateUrl, + OnFailure: 'DO_NOTHING' }; if (parameters.length) { params.Parameters = parameters; @@ -104,4 +105,4 @@ CloudFormation.prototype.updateStack = function (region, stackName, templateUrl, }); }; -module.exports = CloudFormation; \ No newline at end of file +module.exports = CloudFormation; diff --git a/packages/lambda/src/aws/cloudformation.js b/packages/lambda/src/aws/cloudformation.js deleted file mode 100644 index 3b7ac0c8..00000000 --- a/packages/lambda/src/aws/cloudformation.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 Firespring, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const AWS = require('aws-sdk'); - -/** - * CloudFormation constructor - * - * @constructor - */ -function CloudFormation() { -} - -/** - * Get an output from a cloud formation stack - * - * @param region - * @param stackName - * @returns {Promise} - */ -CloudFormation.prototype.describeStacks = (region, stackName) => { - const cloudFormation = new AWS.CloudFormation({region: region}); - return cloudFormation.describeStacks({StackName: stackName}).promise(); -}; - -module.exports = CloudFormation; diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index e7b951e7..5cb873f2 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -16,18 +16,14 @@ 'use strict'; -const CloudFormation = require('../aws/cloudformation'); const SecretsManager = require('../aws/secretsManager'); const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); module.exports = function() { - const cloudFormation = new CloudFormation(); - return cloudFormation.describeStacks(process.env.AWS_REGION, process.env.AWS_STACK_NAME).then(function (stacks) { - const secretId = stacks.Stacks[0].Outputs.find(it => it.OutputKey === 'DatabaseReadwriteSecret').OutputValue; - const secretsManager = new SecretsManager(); - return secretsManager.getSecretValue(process.env.AWS_REGION, secretId); - }).then(function (secret) { + const readwriteSecretId = process.env.AWS_STACK_NAME + "-ReadwriteUserSecret"; + const secretsManager = new SecretsManager(); + secretsManager.getSecretValue(process.env.AWS_REGION, readwriteSecretId).then(function (secret) { const readwriteSecret = JSON.parse(secret.SecretString); return new Sequelize({ host: readwriteSecret.host, @@ -43,7 +39,5 @@ module.exports = function() { connectTimeout: 60000 } }); - }).then(function (sequelize) { - return sequelize; }); }; diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index 56832e51..62a8baa6 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -407,4 +407,4 @@ Repository.prototype.batchQuery = function (builder, results) { }); }; -module.exports = Repository; \ No newline at end of file +module.exports = Repository; From fba9c5eb7d7223b0de9829b9610c4871291ef0cc Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 3 Sep 2020 14:57:10 -0500 Subject: [PATCH 061/140] WIP --- .../templates/givesource-aurora.yml | 43 +++++++++++-------- .../cloudformation/templates/givesource.yml | 22 +--------- packages/lambda/src/models/connect.js | 2 +- 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml index 4bff1da8..3415c178 100644 --- a/packages/cloudformation/templates/givesource-aurora.yml +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -31,6 +31,8 @@ Parameters: Default: givesource StackName: Type: String + LambdaRole: + Type: String LambdaSecurityGroupId: Type: String Resources: @@ -54,7 +56,7 @@ Resources: AdminUserSecret: Type: AWS::SecretsManager::Secret Properties: - Name: !Sub ${AWS::StackName}-AdminUserSecret + Name: !Sub ${StackName}/AdminUserSecret Description: Givesource database auto-generated admin user password GenerateSecretString: SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}", "database": "${DatabaseName}"}' @@ -70,7 +72,7 @@ Resources: MaintenanceUserSecret: Type: AWS::SecretsManager::Secret Properties: - Name: !Sub ${AWS::StackName}-MaintenanceUserSecret + Name: !Sub ${StackName}/MaintenanceUserSecret Description: Givesource database auto-generated maintenance user password GenerateSecretString: SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}", "database": "${DatabaseName}"}' @@ -86,7 +88,7 @@ Resources: ReadwriteUserSecret: Type: AWS::SecretsManager::Secret Properties: - Name: !Sub ${AWS::StackName}-ReadwriteUserSecret + Name: !Sub ${StackName}/ReadwriteUserSecret Description: Givesource database auto-generated readwrite user password GenerateSecretString: SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}", "database": "${DatabaseName}"}' @@ -99,6 +101,20 @@ Resources: SecretId: !Ref ReadwriteUserSecret TargetId: !Ref RDSCluster TargetType: AWS::RDS::DBCluster + SecretsManagerPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: readwrite_user_secret_get + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref ReadwriteUserSecret + Roles: + - !Ref LambdaRole RDSCluster: Type: AWS::RDS::DBCluster Properties: @@ -163,11 +179,11 @@ Resources: Description: Database Init Environment: Variables: - AWS_STACK_NAME: !Ref AWS::StackName + AWS_STACK_NAME: !Ref StackName DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address - ADMIN_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-AdminUserSecret - MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret - READWRITE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-ReadwriteUserSecret + ADMIN_DATABASE_SECRET_ID: !Sub ${StackName}/AdminUserSecret + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${StackName}/MaintenanceUserSecret + READWRITE_DATABASE_SECRET_ID: !Sub ${StackName}/ReadwriteUserSecret DATABASE_NAME: !Ref DatabaseName FunctionName: !Sub ${StackName}-BootstrapDatabase Handler: index.handle @@ -232,9 +248,9 @@ Resources: Description: Database Init Environment: Variables: - AWS_STACK_NAME: !Ref AWS::StackName + AWS_STACK_NAME: !Ref StackName DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address - MAINTENANCE_DATABASE_SECRET_ID: !Sub ${AWS::StackName}-MaintenanceUserSecret + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${StackName}/MaintenanceUserSecret DATABASE_NAME: !Ref DatabaseName MIGRATIONS_BUCKET: {{awsReleaseBucket}} MIGRATIONS_LOCATION: migrations/{{version}} @@ -255,12 +271,3 @@ Resources: Properties: ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn DependsOn: BootstrapDatabaseLambdaLambdaInvoker -Outputs: - ReadwriteUserSecret: - Value: !Sub ${AWS::StackName}-ReadwriteUserSecret - ReadwriteUserSecretArn: - Value: !Ref ReadwriteUserSecret - DatabaseClusterArn: - Value: !Ref RDSCluster - DatabaseEndpoint: - Value: !GetAtt RDSCluster.Endpoint.Address diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index 5b6c539b..a11aa0fd 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -1,4 +1,4 @@ ---- + AWSTemplateFormatVersion: 2010-09-09 Description: AWS Resources for Givesource(R) Parameters: @@ -107,26 +107,11 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId + LambdaRole: !Ref LambdaRole TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 DependsOn: LambdaSecurityGroup - SecretsManagerPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyName: readwrite_user_secret_get - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - secretsmanager:GetSecretValue - Resource: - - !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecretArn - Roles: - - !Ref LambdaRole - DependsOn: AuroraDbStack - S3Stack: Type: AWS::CloudFormation::Stack Properties: @@ -786,9 +771,6 @@ Outputs: LambdaRoleArn: Value: !GetAtt LambdaRole.Arn - DatabaseReadwriteSecret: - Value: !GetAtt AuroraDbStack.Outputs.ReadwriteUserSecret - PublicPagesCloudFrontDistribution: Value: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDistribution diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index 5cb873f2..0d1b1eb5 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -21,7 +21,7 @@ const mysql2 = require('mysql2'); const Sequelize = require('sequelize'); module.exports = function() { - const readwriteSecretId = process.env.AWS_STACK_NAME + "-ReadwriteUserSecret"; + const readwriteSecretId = process.env.AWS_STACK_NAME + "/ReadwriteUserSecret"; const secretsManager = new SecretsManager(); secretsManager.getSecretValue(process.env.AWS_REGION, readwriteSecretId).then(function (secret) { const readwriteSecret = JSON.parse(secret.SecretString); From e061fb963237f39fec05bc131b63f9c376d1192b Mon Sep 17 00:00:00 2001 From: Joe Ebmeier Date: Thu, 3 Sep 2020 15:19:39 -0500 Subject: [PATCH 062/140] WIP --- packages/lambda/src/models/connect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lambda/src/models/connect.js b/packages/lambda/src/models/connect.js index 0d1b1eb5..c59a127a 100644 --- a/packages/lambda/src/models/connect.js +++ b/packages/lambda/src/models/connect.js @@ -23,7 +23,7 @@ const Sequelize = require('sequelize'); module.exports = function() { const readwriteSecretId = process.env.AWS_STACK_NAME + "/ReadwriteUserSecret"; const secretsManager = new SecretsManager(); - secretsManager.getSecretValue(process.env.AWS_REGION, readwriteSecretId).then(function (secret) { + return secretsManager.getSecretValue(process.env.AWS_REGION, readwriteSecretId).then(function (secret) { const readwriteSecret = JSON.parse(secret.SecretString); return new Sequelize({ host: readwriteSecret.host, From 94e00b40a9e0d8be5ef2fbe2ffce025e3653e888 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 7 Sep 2020 10:57:18 -0500 Subject: [PATCH 063/140] GD-1646: Update Users Repository --- .../templates/givesource-custom.yml | 48 +++++ .../account/UserAccountInfoModal.vue | 2 +- .../manageAdmins/ManageAdminsListTable.vue | 6 +- .../manageAdmins/ManageAdminsListTableRow.vue | 4 +- packages/lambda/migrations/00_initial.js | 4 + .../lambda/src/api/getUserProfile/index.js | 6 +- packages/lambda/src/api/getUsers/index.js | 8 +- packages/lambda/src/api/patchUser/index.js | 13 +- packages/lambda/src/api/postUser/index.js | 39 ++-- .../api/resendUserEmailVerification/index.js | 12 +- packages/lambda/src/auth/user.js | 2 +- .../src/custom/cognitoCreateUser/index.js | 22 ++- packages/lambda/src/models/index.js | 2 + packages/lambda/src/models/user.js | 39 ++++ packages/lambda/src/repositories/users.js | 184 +++++++++++++----- 15 files changed, 286 insertions(+), 105 deletions(-) create mode 100644 packages/lambda/src/models/user.js diff --git a/packages/cloudformation/templates/givesource-custom.yml b/packages/cloudformation/templates/givesource-custom.yml index 4adb7f60..236c8bc1 100644 --- a/packages/cloudformation/templates/givesource-custom.yml +++ b/packages/cloudformation/templates/givesource-custom.yml @@ -71,6 +71,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DependsOn: CognitoUserPool AuthorizeUsersLambdaInvokePermission: @@ -156,6 +162,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DependsOn: CognitoCustomMessageFunction CognitoCreateUserPoolClientFunction: @@ -175,6 +187,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCreateUserFunction: Type: AWS::Lambda::Function @@ -193,6 +211,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCreateUserGroupFunction: Type: AWS::Lambda::Function @@ -211,6 +235,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCustomMessageFunction: Type: AWS::Lambda::Function @@ -232,6 +262,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCustomMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -1061,6 +1097,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet MetricMaxAmountLambdaFunction: Type: AWS::Lambda::Function @@ -1079,6 +1121,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet Outputs: diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue index 210e0c1e..c6e3d279 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue @@ -139,7 +139,7 @@ return; } - vue.$request.patch('users/' + vue.user.uuid, params).then(function (response) { + vue.$request.patch('users/' + vue.user.id, params).then(function (response) { vue.removeModal(); if (response.data.errorMessage) { console.log(response.data); diff --git a/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTable.vue b/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTable.vue index ce4fae05..13a7e629 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTable.vue @@ -26,7 +26,7 @@ - + @@ -90,9 +90,9 @@ const vue = this; vue.addModal('spinner'); - vue.$request.delete('users/' + vue.selectedAdminUser.uuid).then(function () { + vue.$request.delete('users/' + vue.selectedAdminUser.id).then(function () { vue.adminUsers = _.filter(vue.adminUsers, function (adminUser) { - return adminUser.uuid !== vue.selectedAdminUser.uuid; + return adminUser.id !== vue.selectedAdminUser.id; }); vue.clearModals(); }).catch(function (err) { diff --git a/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTableRow.vue b/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTableRow.vue index 4bdc95d2..9a827376 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTableRow.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/manageAdmins/ManageAdminsListTableRow.vue @@ -65,7 +65,7 @@ }, computed: { formattedDate: function () { - return new Date(this.adminUser.createdOn).toLocaleDateString(); + return new Date(this.adminUser.createdAt).toLocaleDateString(); }, isSuperAdmin: function () { return _.includes(this.adminUser.groups, 'SuperAdmin'); @@ -106,7 +106,7 @@ const vue = this; vue.addModal('spinner'); - vue.$request.post('users/' + vue.adminUser.uuid + '/resend-verification-email').then(function () { + vue.$request.post('users/' + vue.adminUser.id + '/resend-verification-email').then(function () { vue.clearModals(); }).catch(function (err) { console.log(err); diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index a83a1d73..d9bc8f7a 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -794,6 +794,10 @@ module.exports = { allowNull: false, defaultValue: 0, }, + cognitoUsername: { + type: Sequelize.STRING(2048), + allowNull: false + }, cognitoUuid: { type: Sequelize.STRING(2048), allowNull: false, diff --git a/packages/lambda/src/api/getUserProfile/index.js b/packages/lambda/src/api/getUserProfile/index.js index 5bcd69c1..f5277b03 100644 --- a/packages/lambda/src/api/getUserProfile/index.js +++ b/packages/lambda/src/api/getUserProfile/index.js @@ -24,14 +24,14 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.validate().then(function () { - if (request.user().uuid) { - return repository.get(request.user().uuid); + if (request.user().cognitoUsername) { + return repository.getByCognitoUsername(request.user().cognitoUsername); } else { return Promise.reject(new HttpException('Unable to retrieve user')); } }).then(function (user) { const groups = request.user().groups || []; - callback(null, _.merge({}, user.all(), {groups: groups})); + callback(null, _.merge({}, user, {groups: groups})); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getUsers/index.js b/packages/lambda/src/api/getUsers/index.js index dc968da2..08eeaf9c 100644 --- a/packages/lambda/src/api/getUsers/index.js +++ b/packages/lambda/src/api/getUsers/index.js @@ -33,12 +33,12 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); users.forEach(function (user) { - let result = user.all(); + let result = user; promise = promise.then(function () { - return cognito.listGroupsForUser(process.env.AWS_REGION, userPoolId, user.uuid).then(function (response) { - result.groups = response.hasOwnProperty('Groups') ? response.Groups.map(function (group) { + return cognito.listGroupsForUser(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername')).then(function (response) { + result.setDataValue('groups', response.hasOwnProperty('Groups') ? response.Groups.map(function (group) { return group.GroupName; - }) : []; + }) : []); results.push(result); }); }); diff --git a/packages/lambda/src/api/patchUser/index.js b/packages/lambda/src/api/patchUser/index.js index 12688672..498ba69a 100644 --- a/packages/lambda/src/api/patchUser/index.js +++ b/packages/lambda/src/api/patchUser/index.js @@ -25,17 +25,12 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context); request.middleware(new UserResourceMiddleware(request.urlParam('user_id'))); - let user = null; request.validate().then(function () { return repository.get(request.urlParam('user_id')); - }).then(function (result) { - user = new User(result); - user.populate(request._body); - return user.validate(); - }).then(function () { - return repository.save(user); - }).then(function (model) { - callback(null, model.all()); + }).then(function (populatedUser) { + return repository.upsert(populatedUser, request._body); + }).then(function (user) { + callback(null, user); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/postUser/index.js b/packages/lambda/src/api/postUser/index.js index ae8ba2bb..5f5344a8 100644 --- a/packages/lambda/src/api/postUser/index.js +++ b/packages/lambda/src/api/postUser/index.js @@ -17,9 +17,9 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); +const UUID = require('node-uuid'); exports.handle = function (event, context, callback) { const cognito = new Cognito(); @@ -34,27 +34,26 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); emailAddresses.split(',').forEach(function (email) { email = email.trim(); - const user = new User({email: email}); + let user; promise = promise.then(function () { - return user.validate(['uuid', 'createdOn', 'email']).then(function () { - return cognito.createUser(process.env.AWS_REGION, userPoolId, user.uuid, user.email); - }).then(function (cognitoUser) { - cognitoUser.User.Attributes.forEach(function (attribute) { - if (attribute.Name === 'sub') { - user.cognitoUuid = attribute.Value; - } - }); - }).then(function () { - return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.uuid, 'Admin'); - }).then(function () { - return user.validate(); - }).then(function () { - return usersRepository.save(user); - }).then(function () { - users.push(user.all()); - }).catch(function (err) { - reject(err); + return usersRepository.populate({email: email, cognitoUsername: UUID.v4()}) + }).then(function (populatedUser) { + user = populatedUser; + return cognito.createUser(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername'), user.get('email')); + }).then(function (cognitoUser) { + cognitoUser.User.Attributes.forEach(function (attribute) { + if (attribute.Name === 'sub') { + user.set('cognitoUuid', attribute.Value); + } }); + }).then(function () { + return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername'), 'Admin'); + }).then(function () { + return usersRepository.upsert(user, {}); + }).then(function () { + users.push(user); + }).catch(function (err) { + reject(err); }); }); promise = promise.then(function () { diff --git a/packages/lambda/src/api/resendUserEmailVerification/index.js b/packages/lambda/src/api/resendUserEmailVerification/index.js index 0a7c5d19..f4ee60b4 100644 --- a/packages/lambda/src/api/resendUserEmailVerification/index.js +++ b/packages/lambda/src/api/resendUserEmailVerification/index.js @@ -17,7 +17,6 @@ const Cognito = require('./../../aws/cognito'); const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../dynamo-models/user'); const UserGroupMiddleware = require('./../../middleware/userGroup'); const UsersRepository = require('./../../repositories/users'); @@ -26,17 +25,12 @@ exports.handle = function (event, context, callback) { const repository = new UsersRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin', 'Nonprofit'])); - let user = null; request.validate().then(function () { return repository.get(request.urlParam('user_id')); - }).then(function (result) { - user = new User(result); - user.populate(request._body); - return user.validate(); - }).then(function () { - return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.uuid, user.email, true).catch(function (err) { + }).then(function (user) { + return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.get('cognitoUsername'), user.get('email'), true).catch(function (err) { if (err.code === 'UserNotFoundException') { - return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.uuid, user.email); + return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.get('cognitoUsername'), user.get('email')); } else { return Promise.reject(err); } diff --git a/packages/lambda/src/auth/user.js b/packages/lambda/src/auth/user.js index 0591b886..4f43a8f7 100644 --- a/packages/lambda/src/auth/user.js +++ b/packages/lambda/src/auth/user.js @@ -130,7 +130,7 @@ UserAuthorizer.prototype.authorize = function () { }).then(function (policy) { const user = { groups: authorizer.payload['cognito:groups'], - uuid: authorizer.payload['cognito:username'], + cognitoUsername: authorizer.payload['cognito:username'], }; policy.context = {user: JSON.stringify(user, null, 2)}; resolve(policy); diff --git a/packages/lambda/src/custom/cognitoCreateUser/index.js b/packages/lambda/src/custom/cognitoCreateUser/index.js index 694e572a..97e80eaf 100644 --- a/packages/lambda/src/custom/cognitoCreateUser/index.js +++ b/packages/lambda/src/custom/cognitoCreateUser/index.js @@ -17,8 +17,8 @@ const Cognito = require('./../../aws/cognito'); const logger = require('./../../helpers/log'); const response = require('cfn-response'); -const User = require('./../../dynamo-models/user'); const UsersRepository = require('./../../repositories/users'); +const UUID = require('node-uuid'); exports.handle = function (event, context, callback) { logger.log('cognitoCreateUser event: %j', event); @@ -31,25 +31,29 @@ exports.handle = function (event, context, callback) { const cognito = new Cognito(); const userPoolId = event.ResourceProperties.UserPoolId; const email = event.ResourceProperties.Email; + const uuid = UUID.v4(); + let user; const repository = new UsersRepository(); - const user = new User({email: email}); + const userData = {email: email, cognitoUsername: uuid}; - user.validate(['uuid', 'createdOn', 'email']).then(function () { - return cognito.createUser(process.env.AWS_REGION, userPoolId, user.uuid, user.email); + let promise = Promise.resolve(); + promise.then(function () { + return cognito.createUser(process.env.AWS_REGION, userPoolId, uuid, email); }).then(function (cognitoUser) { logger.log(JSON.stringify(cognitoUser)); cognitoUser.User.Attributes.forEach(function (attribute) { if (attribute.Name === 'sub') { - user.cognitoUuid = attribute.Value; + userData.cognitoUuid = attribute.Value; } }); }).then(function () { - return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.uuid, 'SuperAdmin'); + return repository.populate(userData); + }).then(function (populatedUser) { + user = populatedUser; + return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername'), 'SuperAdmin'); }).then(function () { - return user.validate(); - }).then(function () { - return repository.save(user); + return repository.upsert(user, {}); }).then(function () { response.send(event, context, response.SUCCESS); }).catch(function (err) { diff --git a/packages/lambda/src/models/index.js b/packages/lambda/src/models/index.js index 998a4df2..911378e9 100644 --- a/packages/lambda/src/models/index.js +++ b/packages/lambda/src/models/index.js @@ -33,6 +33,8 @@ module.exports = function() { models[model.name] = model; model = require('./file')(sequelize); models[model.name] = model; + model = require('./user')(sequelize); + models[model.name] = model; return models; }); } diff --git a/packages/lambda/src/models/user.js b/packages/lambda/src/models/user.js new file mode 100644 index 00000000..628b41f5 --- /dev/null +++ b/packages/lambda/src/models/user.js @@ -0,0 +1,39 @@ +'use strict'; + +const {DataTypes} = require('sequelize'); + +module.exports = (sequelize) => { + return sequelize.define('User', { + email: { + type: DataTypes.STRING, + allowNull: false, + }, + firstName: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '' + }, + lastName: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '' + }, + isVerified: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + nonprofitId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + cognitoUsername: { + type: DataTypes.STRING, + allowNull: false, + }, + cognitoUuid: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '' + }, + }); +}; \ No newline at end of file diff --git a/packages/lambda/src/repositories/users.js b/packages/lambda/src/repositories/users.js index 26055a8e..fbe9ff17 100644 --- a/packages/lambda/src/repositories/users.js +++ b/packages/lambda/src/repositories/users.js @@ -18,6 +18,7 @@ const User = require('./../dynamo-models/user'); const Repository = require('./repository'); const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); +const loadModels = require('../models/index'); /** * UsersRepository constructor @@ -39,22 +40,78 @@ function UsersRepository(options) { */ UsersRepository.prototype = new Repository(); +/** + * Look to abstract this + * + * @param data + * @return {Promise} + */ +UsersRepository.prototype.populate = function (data) { + let allModels; + return loadModels().then(function (models) { + allModels = models; + return new models.User(data); + }).finally(function () { + return allModels.sequelize.close(); + }); +}; + /** * Get a User * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -UsersRepository.prototype.get = function (uuid) { - const repository = this; +UsersRepository.prototype.get = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.getByKey('uuid', uuid).then(function (data) { - if (data.hasOwnProperty('Item')) { - resolve(new User(data.Item)); - } - reject(new ResourceNotFoundException('The specified user does not exist.')); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.findOne({ + where: { + id: id + } + }).then(function (user) { + if (user instanceof allModels.User) { + resolve(user); + } + reject(new ResourceNotFoundException('The specified user does not exist.')); + }); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Get a User by cognitoUsername + * + * @param {String} cognitoUsername + * @return {Promise} + */ +UsersRepository.prototype.getByCognitoUsername = function (cognitoUsername) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.findOne({ + where: { + cognitoUsername: cognitoUsername + } + }).then(function (user) { + if (user instanceof allModels.User) { + resolve(user); + } + reject(new ResourceNotFoundException('The specified user does not exist.')); + }); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -65,18 +122,18 @@ UsersRepository.prototype.get = function (uuid) { * @return {Promise} */ UsersRepository.prototype.getAll = function () { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - repository.batchScan().then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new User(item)); - }); - } + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.findAll(); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -87,21 +144,22 @@ UsersRepository.prototype.getAll = function () { * @return {Promise} */ UsersRepository.prototype.getAdminUsers = function () { - const repository = this; + let allModels; return new Promise(function (resolve, reject) { - const params = { - FilterExpression: 'attribute_not_exists(nonprofitUuid)' - }; - repository.batchScan(params).then(function (data) { - let results = []; - if (data.Items) { - data.Items.forEach(function (item) { - results.push(new User(item)); - }); - } + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.findAll({ + where: { + nonprofitId: '' + } + }); + }).then(function (results) { resolve(results); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; @@ -109,42 +167,80 @@ UsersRepository.prototype.getAdminUsers = function () { /** * Delete a User * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -UsersRepository.prototype.delete = function (uuid) { - const repository = this; +UsersRepository.prototype.delete = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.deleteByKey('uuid', uuid).then(function () { - resolve(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.destroy({where: {id: id}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; /** - * Create or update a User + * Update a User * * @param {User} model */ UsersRepository.prototype.save = function (model) { + let allModels; const repository = this; return new Promise(function (resolve, reject) { - if (!(model instanceof User)) { - reject(new Error('invalid User model')); - } - model.validate().then(function () { - const key = { - uuid: model.uuid - }; - repository.put(key, model.except(['uuid'])).then(function (data) { - resolve(new User(data.Attributes)); - }).catch(function (err) { - reject(err); + return loadModels().then(function (models) { + allModels = models; + if (!(model instanceof allModels.User)) { + reject(new Error('invalid User model')); + } + return repository.upsert(model, {}); + }).then(function (user) { + resolve(user); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + +/** + * Insert or update the model + * + * @param {Object} model + * @param {Object} data + * @return {Promise} + */ +UsersRepository.prototype.upsert = function (model, data) { + let allModels; + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.User.upsert({ + 'id': model.get('id'), + 'email': typeof data.email !== "undefined" ? data.email : model.get('email'), + 'firstName': typeof data.firstName !== "undefined" ? data.firstName : model.get('firstName'), + 'lastName': typeof data.lastName !== "undefined" ? data.lastName : model.get('lastName'), + 'isVerified': typeof data.isVerified !== "undefined" ? data.isVerified : model.get('isVerified'), + 'nonprofitId': typeof data.nonprofitId !== "undefined" ? data.nonprofitId : model.get('nonprofitId'), + 'cognitoUsername': typeof data.cognitoUsername !== "undefined" ? data.cognitoUsername : model.get('cognitoUsername'), + 'cognitoUuid': typeof data.cognitoUuid !== "undefined" ? data.cognitoUuid : model.get('cognitoUuid'), }); + }).then(function (user) { + resolve(user); }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; From 283d8e542a046392855c8a03e22da3b2104c806a Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 9 Sep 2020 09:56:29 -0500 Subject: [PATCH 064/140] GD-1646: Update Users Repository --- .../components/account/UserAccountInfoModal.vue | 2 +- packages/lambda/src/api/patchUser/index.js | 3 +-- packages/lambda/src/middleware/userResource.js | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue index c6e3d279..e05b162d 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue @@ -139,7 +139,7 @@ return; } - vue.$request.patch('users/' + vue.user.id, params).then(function (response) { + vue.$request.patch('users/' + vue.user.cognitoUsername, params).then(function (response) { vue.removeModal(); if (response.data.errorMessage) { console.log(response.data); diff --git a/packages/lambda/src/api/patchUser/index.js b/packages/lambda/src/api/patchUser/index.js index 498ba69a..ae376d1e 100644 --- a/packages/lambda/src/api/patchUser/index.js +++ b/packages/lambda/src/api/patchUser/index.js @@ -16,7 +16,6 @@ const HttpException = require('./../../exceptions/http'); const Request = require('./../../aws/request'); -const User = require('./../../dynamo-models/user'); const UserResourceMiddleware = require('./../../middleware/userResource'); const UsersRepository = require('./../../repositories/users'); @@ -26,7 +25,7 @@ exports.handle = function (event, context, callback) { request.middleware(new UserResourceMiddleware(request.urlParam('user_id'))); request.validate().then(function () { - return repository.get(request.urlParam('user_id')); + return repository.getByCognitoUsername(request.urlParam('user_id')); }).then(function (populatedUser) { return repository.upsert(populatedUser, request._body); }).then(function (user) { diff --git a/packages/lambda/src/middleware/userResource.js b/packages/lambda/src/middleware/userResource.js index a384e40f..d5378857 100644 --- a/packages/lambda/src/middleware/userResource.js +++ b/packages/lambda/src/middleware/userResource.js @@ -21,11 +21,11 @@ const Middleware = require('./middleware'); /** * UserResourceMiddleware constructor * - * @param {String} userUuid + * @param {String} cognitoUsername * @constructor */ -function UserResourceMiddleware(userUuid) { - this.userUuid = userUuid; +function UserResourceMiddleware(cognitoUsername) { + this.cognitoUsername = cognitoUsername; } /** @@ -44,7 +44,7 @@ UserResourceMiddleware.prototype.handle = function () { const middleware = this; return new Promise(function (resolve, reject) { - if (middleware.user.uuid === middleware.userUuid) { + if (middleware.user.cognitoUsername === middleware.cognitoUsername) { return resolve(); } From 8e09745b0cb2852cd2c9f06e25d28b6aeb7ba6d6 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 9 Sep 2020 15:37:41 -0500 Subject: [PATCH 065/140] GD-1645: Update Sponsors Repository --- .../components/admin/settings/contact/ContactSettings.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/settings/contact/ContactSettings.vue b/packages/frontend/src/admin-pages/components/admin/settings/contact/ContactSettings.vue index d5c12631..62685793 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/contact/ContactSettings.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/contact/ContactSettings.vue @@ -137,10 +137,10 @@ }, computed: { displayResendContactEmailVerificationLink: function () { - return this.settings.length && this.emailSettings.length && !this.contactEmailIsVerified; + return this.settings.length && this.contactEmail !== null && this.emailSettings.length && !this.contactEmailIsVerified; }, displayResendSenderEmailVerificationLink: function () { - return this.settings.length && this.emailSettings.length && !this.senderEmailIsVerified; + return this.settings.length && this.senderEmail !== null && this.emailSettings.length && !this.senderEmailIsVerified; }, contactEmail: function () { let setting = null; From 72b24d055196ec24a850dcc344aae4235baa09e1 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 14 Sep 2020 09:48:54 -0500 Subject: [PATCH 066/140] GD-1645: Update Sponsors Repository --- .../components/admin/pages/Homepage.vue | 14 +++++-- .../admin/settings/appearance/Appearance.vue | 8 ++-- .../settings/socialSharing/SocialSharing.vue | 41 ++----------------- .../nonprofit/yourPage/tabs/Content.vue | 6 +-- packages/lambda/src/api/deleteFiles/index.js | 11 +++-- .../lambda/src/api/patchContents/index.js | 23 ++++------- .../lambda/src/api/patchSettings/index.js | 3 ++ packages/lambda/src/repositories/files.js | 22 ++++++---- packages/lambda/src/repositories/settings.js | 5 ++- 9 files changed, 55 insertions(+), 78 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/pages/Homepage.vue b/packages/frontend/src/admin-pages/components/admin/pages/Homepage.vue index f16992dc..ebe7135e 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/Homepage.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/Homepage.vue @@ -354,6 +354,11 @@ ] }).then(function (response) { contents = response.data; + contents.forEach(function (content) { + if (content.key === 'HOMEPAGE_MATCH_IS_ENABLED') { + content.value = content.value !== "0"; + } + }); }); }); @@ -522,7 +527,7 @@ promise = promise.then(function () { return vue.$request.patch('contents', { contents: toUpdate.map(function (content) { - return _.pick(content, ['key', 'sortOrder', 'type', 'uuid', 'value']); + return _.pick(content, ['key', 'sortOrder', 'type', 'id', 'value']); }), }); }); @@ -589,12 +594,13 @@ return vue.uploadFile(vue.formData.contents[key]).then(function (uploadedFile) { vue.$store.commit('generateCacheKey'); contents[key] = _.cloneDeep(vue.formData.contents[key]); - contents[key].value = uploadedFile && uploadedFile.hasOwnProperty('uuid') ? uploadedFile.uuid : ''; + contents[key].value = uploadedFile && uploadedFile.hasOwnProperty('id') ? uploadedFile.id.toString() : ''; + contents[key].file = uploadedFile; }); }); } else { promise = promise.then(function () { - const contentValue = _.isPlainObject(vue.formData.contents[key].value) && vue.formData.contents[key].value.hasOwnProperty('uuid') ? vue.formData.contents[key].value.uuid : vue.formData.contents[key].value; + const contentValue = _.isPlainObject(vue.formData.contents[key].value) && vue.formData.contents[key].value.hasOwnProperty('id') ? vue.formData.contents[key].value.id.toString() : vue.formData.contents[key].value; contents[key] = _.cloneDeep(vue.formData.contents[key]); contents[key].value = contentValue; }); @@ -618,7 +624,7 @@ } settings.push({ key: key, - value: value + value: value.toString() }); }); diff --git a/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue b/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue index 1c96ec85..90a70991 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue @@ -324,7 +324,7 @@ vue.$store.commit('generateCacheKey'); settings.push({ key: key, - value: uploadedFile && uploadedFile.hasOwnProperty('uuid') ? uploadedFile.uuid : '' + value: uploadedFile && uploadedFile.hasOwnProperty('id') ? uploadedFile.id.toString() : '' }); }); }); @@ -333,12 +333,12 @@ let settingValue = vue.formData[key]; if (key === 'ACCENT_COLOR' && vue.formData[key] === vue.defaultColor) { settingValue = ''; - } else if (_.isPlainObject(vue.formData[key]) && vue.formData[key].hasOwnProperty('uuid')) { - settingValue = vue.formData[key].uuid; + } else if (_.isPlainObject(vue.formData[key]) && vue.formData[key].hasOwnProperty('id')) { + settingValue = vue.formData[key].id; } settings.push({ key: key, - value: settingValue + value: settingValue.toString() }); }); } diff --git a/packages/frontend/src/admin-pages/components/admin/settings/socialSharing/SocialSharing.vue b/packages/frontend/src/admin-pages/components/admin/settings/socialSharing/SocialSharing.vue index c40b7d37..02deccfe 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/socialSharing/SocialSharing.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/socialSharing/SocialSharing.vue @@ -209,42 +209,9 @@ const toUpdate = _.reject(settings, setting => { return (setting.value === '' || setting.value === null); }); - const toDelete = _.filter(settings, setting => { - return (setting.value === '' || setting.value === null); - }); vm.$request.patch('settings', { settings: toUpdate - }).then(response => { - if (response.data.errorMessage) { - console.log(response.data); - } - return vm.$request.delete('settings', { - settings: toDelete - }); - }).then(response => { - if (response.data.errorMessage) { - console.log(response.data); - } - - // delete files that were replace or removed - const filesToDelete = []; - _.forEach(settings, setting => { - if (vm.isFileSetting(setting.key)) { - const originalSetting = _.find(vm.settings, {key: setting.key}); - if (originalSetting && originalSetting.value !== setting.value && originalSetting.value !== '' && originalSetting.value !== null) { - filesToDelete.push(originalSetting.value); - } - } - }); - - if (filesToDelete.length > 0) { - return vm.$request.delete('files', { - files: filesToDelete - }); - } - - return Promise.resolve(); }).then(() => { vm.clearModals(); vm.$router.push({name: 'settings-list'}); @@ -268,19 +235,19 @@ vm.$store.commit('generateCacheKey'); settings.push({ key: key, - value: uploadedFile && uploadedFile.hasOwnProperty('uuid') ? uploadedFile.uuid : '' + value: uploadedFile && uploadedFile.hasOwnProperty('id') ? uploadedFile.id.toString() : '' }); }); }); } else { promise = promise.then(() => { let settingValue = vm.formData[key]; - if (_.isPlainObject(vm.formData[key]) && vm.formData[key].hasOwnProperty('uuid')) { - settingValue = vm.formData[key].uuid; + if (_.isPlainObject(vm.formData[key]) && vm.formData[key].hasOwnProperty('id')) { + settingValue = vm.formData[key].id; } settings.push({ key: key, - value: settingValue + value: settingValue.toString() }); }); } diff --git a/packages/frontend/src/admin-pages/components/nonprofit/yourPage/tabs/Content.vue b/packages/frontend/src/admin-pages/components/nonprofit/yourPage/tabs/Content.vue index 9e823ee8..18ce8b76 100644 --- a/packages/frontend/src/admin-pages/components/nonprofit/yourPage/tabs/Content.vue +++ b/packages/frontend/src/admin-pages/components/nonprofit/yourPage/tabs/Content.vue @@ -254,11 +254,11 @@ promise = promise.then(function () { return vue.uploadFile('logo').then(function (uploadedFile) { vue.$store.commit('generateCacheKey'); - vue.formData.logoFileUuid = uploadedFile && uploadedFile.hasOwnProperty('uuid') ? uploadedFile.uuid : ''; + vue.formData.logoFileUuid = uploadedFile && uploadedFile.hasOwnProperty('id') ? uploadedFile.id : ''; }); }); - } else if (_.isPlainObject(vue.formData.logo) && vue.formData.logo.hasOwnProperty('uuid')) { - vue.formData.logoFileUuid = vue.formData.logo.uuid; + } else if (_.isPlainObject(vue.formData.logo) && vue.formData.logo.hasOwnProperty('id')) { + vue.formData.logoFileUuid = vue.formData.logo.id; } else { vue.formData.logoFileUuid = ''; } diff --git a/packages/lambda/src/api/deleteFiles/index.js b/packages/lambda/src/api/deleteFiles/index.js index da7baa05..f9a47c4f 100644 --- a/packages/lambda/src/api/deleteFiles/index.js +++ b/packages/lambda/src/api/deleteFiles/index.js @@ -14,7 +14,6 @@ * limitations under the License. */ -const File = require('./../../dynamo-models/file'); const FilesRepository = require('./../../repositories/files'); const HttpException = require('./../../exceptions/http'); const Lambda = require('./../../aws/lambda'); @@ -28,18 +27,18 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['files']); const s3 = new S3(); - let files = []; request.validate().then(function () { let promise = Promise.resolve(); request.get('files', []).forEach(function (file) { - files.push(new File(file)); promise = promise.then(function () { - return s3.deleteObject(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, `uploads/${file.uuid}`); + return repository.get(file); + }).then(function (file) { + return s3.deleteObject(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, file.get('path')); + }).then(function () { + return repository.delete(file); }); }); return promise; - }).then(function () { - return repository.batchDelete(files); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/patchContents/index.js b/packages/lambda/src/api/patchContents/index.js index 2cad77b5..99274438 100644 --- a/packages/lambda/src/api/patchContents/index.js +++ b/packages/lambda/src/api/patchContents/index.js @@ -24,26 +24,21 @@ exports.handle = function (event, context, callback) { const lambda = new Lambda(); const repository = new ContentsRepository(); const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['contents']); + const keys = request.get('contents', []).map(function (content) { + return content.key; + }); - let contents = []; request.validate().then(function () { + return repository.batchGet(keys); + }).then(function (oldContents) { let promise = Promise.resolve(); request.get('contents', []).map(function (content) { promise = promise.then(function () { - return repository.populate(content); - }).then(function (model) { - if (Array.isArray(model.get('value'))) { - model.set('value', ''); + if (Array.isArray(content.value) || typeof content.value === 'object') { + content.value = ''; } - contents.push(model); - }); - }); - return promise; - }).then(function () { - let promise = Promise.resolve(); - contents.forEach(function (model) { - promise = promise.then(function () { - return repository.upsert(model, {}); + const oldContent = _.find(oldContents, {key: content.key}); + return repository.upsert(oldContent, content); }); }); return promise; diff --git a/packages/lambda/src/api/patchSettings/index.js b/packages/lambda/src/api/patchSettings/index.js index 5ea1d866..ce31d060 100644 --- a/packages/lambda/src/api/patchSettings/index.js +++ b/packages/lambda/src/api/patchSettings/index.js @@ -44,6 +44,9 @@ exports.handle = function (event, context, callback) { return repository.populate(data); } }).then(function (model) { + if (Array.isArray(data.value) || typeof data.value === 'object') { + delete data.value; + } return repository.upsert(model, data); }).then(function (savedModel) { settings.push(savedModel); diff --git a/packages/lambda/src/repositories/files.js b/packages/lambda/src/repositories/files.js index 28e6af29..146e8257 100644 --- a/packages/lambda/src/repositories/files.js +++ b/packages/lambda/src/repositories/files.js @@ -73,9 +73,9 @@ FilesRepository.prototype.get = function (id) { where: { id: id } - }).then(function (setting) { - if (setting instanceof allModels.File) { - resolve(setting); + }).then(function (file) { + if (file instanceof allModels.File) { + resolve(file); } reject(new ResourceNotFoundException('The specified file does not exist.')); }); @@ -141,16 +141,22 @@ FilesRepository.prototype.batchGet = function (fileIds) { /** * Delete a File * - * @param {String} uuid + * @param {String} id * @return {Promise} */ -FilesRepository.prototype.delete = function (uuid) { - const repository = this; +FilesRepository.prototype.delete = function (id) { + let allModels; return new Promise(function (resolve, reject) { - repository.deleteByKey('uuid', uuid).then(function () { - resolve(); + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.File.destroy({where: {id: id}}); + }).then(function () { + resolve() }).catch(function (err) { reject(err); + }).finally(function () { + return allModels.sequelize.close(); }); }); }; diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index d7f4c01a..a191b0f1 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -43,14 +43,15 @@ SettingsRepository.prototype = new Repository(); /** * Look to abstract this * - * @param data + * @param {Object} data * @return {Promise} */ SettingsRepository.prototype.populate = function (data) { let allModels; return loadModels().then(function (models) { allModels = models; - return new models.Setting(data); + const setting = new models.Setting(); + return new setting.constructor(data, {isNewRecord: typeof data.id === 'undefined'}); }).finally(function () { return allModels.sequelize.close(); }); From d6c3dc95e9cf93050b7bf1c89badf238a5a8f35f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Mon, 14 Sep 2020 15:18:05 -0500 Subject: [PATCH 067/140] GD-1645: Update Sponsors Repository --- .../components/admin/settings/appearance/Appearance.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue b/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue index 90a70991..1495fb2c 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/appearance/Appearance.vue @@ -338,7 +338,7 @@ } settings.push({ key: key, - value: settingValue.toString() + value: settingValue !== null ? settingValue.toString() : settingValue }); }); } From 04dc366dccacdf885636cda447fd77c003ea5046 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 15 Sep 2020 14:44:57 -0500 Subject: [PATCH 068/140] GD-1645: WIP --- .../components/admin/pages/PagesList.vue | 24 ++++++---- .../components/admin/pages/Toolkits.vue | 2 +- .../pages/custom/CustomPagesDeleteModal.vue | 6 +-- .../admin/pages/custom/CustomPagesEdit.vue | 8 ++-- .../admin/pages/toolkit/AddResourceModal.vue | 6 +-- .../SponsorsTiersListTableRow.vue | 2 +- .../frontend/src/admin-pages/router/index.js | 2 +- .../lambda/src/api/deleteContents/index.js | 6 ++- packages/lambda/src/api/deleteFiles/index.js | 6 ++- .../lambda/src/api/deleteSettings/index.js | 6 ++- .../lambda/src/api/deleteSponsors/index.js | 4 +- packages/lambda/src/api/patchSetting/index.js | 8 ++-- packages/lambda/src/api/postSetting/index.js | 6 +-- packages/lambda/src/repositories/contents.js | 46 ++++++++++++------- packages/lambda/src/repositories/settings.js | 28 +++++------ .../lambda/src/repositories/sponsorTiers.js | 3 +- packages/lambda/src/repositories/sponsors.js | 3 +- 17 files changed, 98 insertions(+), 68 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/pages/PagesList.vue b/packages/frontend/src/admin-pages/components/admin/pages/PagesList.vue index fc3126b0..b4e6baad 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/PagesList.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/PagesList.vue @@ -222,7 +222,7 @@
- {{ content.title }} + {{ content.title }} — {{ getPageUrl('/' + content.slug) }}
@@ -232,8 +232,8 @@
- + :name="content.id" :id="content.id" :disabled="content.updating"> +
@@ -273,6 +273,14 @@ ] }).then((response) => { settings = response.hasOwnProperty('data') ? response.data : []; + settings.forEach(function (setting) { + if (setting.value === "0") { + setting.value = false; + } + if (setting.value === "1") { + setting.value = true; + } + }); const keys = getSettingKeys(settings); if (keys.length) { @@ -338,21 +346,21 @@ vm.settings = data.settings; const setting = _.find(vm.settings, {key: 'CUSTOM_PAGES'}); - const uuids = (typeof setting === 'object' && setting.hasOwnProperty('value')) ? setting.value.split('|') : []; + const ids = (typeof setting === 'object' && setting.hasOwnProperty('value')) ? setting.value.split('|') : []; - if (uuids.length < 3) { + if (ids.length < 3) { vm.canAddPages = true; } - uuids.forEach((uuid) => { + ids.forEach((id) => { const content = { enabled: false, - identifier: uuid.toUpperCase().replace(/-/g, '_'), + identifier: id.toUpperCase().replace(/-/g, '_'), slug: null, text: null, title: null, updating: false, - uuid: uuid, + id: id, }; vm.contents.forEach((c) => { if (c.key.includes(content.identifier)) { diff --git a/packages/frontend/src/admin-pages/components/admin/pages/Toolkits.vue b/packages/frontend/src/admin-pages/components/admin/pages/Toolkits.vue index f447e93a..0d775c4f 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/Toolkits.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/Toolkits.vue @@ -252,7 +252,7 @@ promise = promise.then(function () { return vue.$request.patch('contents', { contents: toUpdate.map(function (content) { - return _.pick(content, ['key', 'sortOrder', 'type', 'uuid', 'value']); + return _.pick(content, ['key', 'sortOrder', 'type', 'id', 'value']); }), }); }); diff --git a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesDeleteModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesDeleteModal.vue index ad7e6222..19678354 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesDeleteModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesDeleteModal.vue @@ -63,7 +63,7 @@ default: { contents: [], settings: [], - pageUuid: null + pageId: null } } }, @@ -82,7 +82,7 @@ const setting = _.find(vm.data.settings, {key: 'CUSTOM_PAGES'}); const uuids = setting.value.split('|'); const updatedUuids = uuids.filter((uuid) => { - return uuid !== vm.data.pageUuid; + return uuid !== vm.data.pageId; }); let promise = Promise.resolve(); @@ -102,7 +102,7 @@ } promise = promise.then(() => { - const keys = getSettingKeys(vm.data.pageUuid); + const keys = getSettingKeys(vm.data.pageId); const toDelete = []; keys.forEach((key) => { diff --git a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue index b63947d6..3d733a39 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue @@ -187,13 +187,13 @@ } }, props: { - pageUuid: { + pageId: { type: String, default: '' } }, beforeRouteEnter(to, from, next) { - fetchData(to.params.pageUuid).then((data) => { + fetchData(to.params.pageId).then((data) => { next((vm) => { vm.contents = data.contents; vm.settings = data.settings; @@ -311,7 +311,7 @@ vm.addModal('pages-custom-delete-modal', { contents: vm.contents, settings: vm.settings, - pageUuid: vm.pageUuid + pageId: vm.pageId }); }, editSlug() { @@ -320,7 +320,7 @@ cancelEditSlug() { const vm = this; - const identifier = vm.pageUuid.toUpperCase().replace(/-/g, '_'); + const identifier = vm.pageId.toUpperCase().replace(/-/g, '_'); const content = _.find(vm.contents, {key: 'CUSTOM_PAGE_SLUG_' + identifier}); vm.formData.PAGE_SLUG.value = content.value; diff --git a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/AddResourceModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/AddResourceModal.vue index ddc19bb6..b25fdd81 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/AddResourceModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/AddResourceModal.vue @@ -271,7 +271,7 @@ axios.defaults.headers = defaultHeaders; return instance.put(signedUrl, vue.formData.TOOLKIT_RESOURCE_LIST_ITEM_FILE.value); }).then(function () { - vue.formData.TOOLKIT_RESOURCE_LIST_ITEM_FILE.value = file.uuid; + vue.formData.TOOLKIT_RESOURCE_LIST_ITEM_FILE.value = file.id; }); } @@ -282,11 +282,11 @@ type: 'COLLECTION' }); }).then(function (response) { - toolkitResourceListContent = response.data; + toolkitResourceListContent = response.data[0]; return vue.$request.patch('contents', { contents: Object.keys(vue.formData).map(function (key) { const content = vue.formData[key]; - content.parentUuid = toolkitResourceListContent.uuid; + content.parentId = toolkitResourceListContent.id; return content; }), }); diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue index 76f9d10e..10e2a13b 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/SponsorsTiersListTableRow.vue @@ -105,7 +105,7 @@ } }); return vue.$request.get('files', { - uuids: fileIds + fileIds: fileIds }); }).then(function (response) { return vue.$request.delete('files', { diff --git a/packages/frontend/src/admin-pages/router/index.js b/packages/frontend/src/admin-pages/router/index.js index fa212982..90985f72 100644 --- a/packages/frontend/src/admin-pages/router/index.js +++ b/packages/frontend/src/admin-pages/router/index.js @@ -244,7 +244,7 @@ const router = new VueRouter({ }, }, { - path: '/pages/custom/:pageUuid', + path: '/pages/custom/:pageId', name: 'pages-custom-edit', props: true, component: ComponentCustomPagesEdit, diff --git a/packages/lambda/src/api/deleteContents/index.js b/packages/lambda/src/api/deleteContents/index.js index 75edb723..39682da5 100644 --- a/packages/lambda/src/api/deleteContents/index.js +++ b/packages/lambda/src/api/deleteContents/index.js @@ -32,9 +32,11 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); request.get('contents', []).forEach(async function (data) { promise = promise.then(function () { - return repository.populate(data); + return repository.get(data.id, true); }).then(function (content) { - contents.push(content); + if (content !== null) { + contents.push(content); + } }); }); return promise; diff --git a/packages/lambda/src/api/deleteFiles/index.js b/packages/lambda/src/api/deleteFiles/index.js index f9a47c4f..57e0ae15 100644 --- a/packages/lambda/src/api/deleteFiles/index.js +++ b/packages/lambda/src/api/deleteFiles/index.js @@ -31,7 +31,11 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); request.get('files', []).forEach(function (file) { promise = promise.then(function () { - return repository.get(file); + if (typeof file === 'object') { + return repository.get(file.id); + } else { + return repository.get(file); + } }).then(function (file) { return s3.deleteObject(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, file.get('path')); }).then(function () { diff --git a/packages/lambda/src/api/deleteSettings/index.js b/packages/lambda/src/api/deleteSettings/index.js index d4d6a64d..3b09d92d 100644 --- a/packages/lambda/src/api/deleteSettings/index.js +++ b/packages/lambda/src/api/deleteSettings/index.js @@ -31,9 +31,11 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); request.get('settings', []).forEach(function (data) { promise = promise.then(function () { - return repository.populate(data); + return repository.get(data.key, true); }).then(function (setting) { - settings.push(setting); + if (setting !== null) { + settings.push(setting); + } }); }); return promise; diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index 5779f601..dee2069d 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -30,14 +30,14 @@ exports.handle = function (event, context, callback) { let promise = Promise.resolve(); request.get('sponsors', []).forEach(function (data) { promise = promise.then(function () { - return repository.populate(data); + return repository.get(request.urlParam('sponsor_tier_id'), data.id); }).then(function (sponsor) { sponsors.push(sponsor); }); }); return promise; }).then(function () { - return repository.batchRemove(request.urlParam('sponsor_tier_id'), sponsors); + return repository.batchDelete(sponsors); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/api/patchSetting/index.js b/packages/lambda/src/api/patchSetting/index.js index c454a164..1653a097 100644 --- a/packages/lambda/src/api/patchSetting/index.js +++ b/packages/lambda/src/api/patchSetting/index.js @@ -30,15 +30,15 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return repository.get(request.urlParam('key')); }).then(function (setting) { - setting.set('value', request._body.value); + setting.value = request._body.value; return setting.validate(); - }).then(function (setting) { - return repository.save(setting); + }).then(function (validSetting) { + return repository.save(validSetting); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - return DynamicContentHelper.regenerateDynamicContent([setting.get('key')], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); + return DynamicContentHelper.regenerateDynamicContent([setting.key], process.env.AWS_REGION, process.env.AWS_STACK_NAME, false); }).then(function () { callback(null, setting); }).catch(function (err) { diff --git a/packages/lambda/src/api/postSetting/index.js b/packages/lambda/src/api/postSetting/index.js index 7b396605..3de49a2b 100644 --- a/packages/lambda/src/api/postSetting/index.js +++ b/packages/lambda/src/api/postSetting/index.js @@ -38,10 +38,8 @@ exports.handle = function (event, context, callback) { }); }).then(function () { return repository.populate(request._body); - }).then(function () { - return setting.validate(); - }).then(function () { - return repository.save(setting); + }).then(function (setting) { + return repository.upsert(setting, {}); }).then(function (response) { setting = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); diff --git a/packages/lambda/src/repositories/contents.js b/packages/lambda/src/repositories/contents.js index 4e01c385..8bf3bda7 100644 --- a/packages/lambda/src/repositories/contents.js +++ b/packages/lambda/src/repositories/contents.js @@ -50,7 +50,8 @@ ContentsRepository.prototype.populate = function (data) { let allModels; return loadModels().then(function (models) { allModels = models; - return new models.Content(data); + const content = new models.Content(); + return new content.constructor(data, {isNewRecord: typeof data.id === 'undefined'}); }).finally(function () { return allModels.sequelize.close(); }) @@ -60,9 +61,10 @@ ContentsRepository.prototype.populate = function (data) { * Get a Content * * @param {String} id + * @param {Boolean} returnNull * @return {Promise} */ -ContentsRepository.prototype.get = function (id) { +ContentsRepository.prototype.get = function (id, returnNull = false) { let allModels; return new Promise(function (resolve, reject) { return loadModels().then(function (models) { @@ -73,7 +75,7 @@ ContentsRepository.prototype.get = function (id) { id: id } }).then(function (content) { - if (content instanceof allModels.Content) { + if (content instanceof allModels.Content || returnNull) { resolve(content); } reject(new ResourceNotFoundException('The specified content does not exist.')); @@ -181,17 +183,23 @@ ContentsRepository.prototype.batchGet = function (keys) { */ ContentsRepository.prototype.batchDelete = function (models) { let allModels; + const ids = models.map(function (model) { + return model.id; + }); return new Promise(function (resolve, reject) { - return loadModels().then(function (models) { - allModels = models; + return loadModels().then(function (loadedModels) { + allModels = loadedModels; }).then(function () { - let promise = Promise.resolve(); - promise = promise.then(function () { - models.forEach(function (model) { - return model.destroy(); + if (ids.length > 0) { + return allModels.Content.destroy({ + where: { + id: { + [Sequelize.Op.or]: ids + } + } }) - }); - return promise; + } + resolve(); }).then(function (stuff) { resolve(stuff); }).catch(function (err) { @@ -332,13 +340,17 @@ ContentsRepository.prototype.upsert = function (model, data) { return loadModels().then(function (models) { allModels = models; }).then(function () { + if (typeof model === 'undefined') { + const content = new allModels.Content(); + model = new content.constructor({}, {isNewRecord: typeof data.id === 'undefined'}); + } return allModels.Content.upsert({ - 'id': model.get('id'), - 'key': typeof data.key !== "undefined" ? data.key : model.get('key'), - 'value': typeof data.value !== "undefined" ? data.value : model.get('value'), - 'sortOrder': typeof data.sortOrder !== "undefined" ? data.sortOrder : model.get('sortOrder'), - 'type': typeof data.type !== "undefined" ? data.type : model.get('type'), - 'parentId': typeof data.parentId !== "undefined" ? data.parentId : model.get('parentId'), + 'id': model.id, + 'key': typeof data.key !== "undefined" ? data.key : model.key, + 'value': typeof data.value !== "undefined" ? data.value : model.value, + 'sortOrder': typeof data.sortOrder !== "undefined" ? data.sortOrder : model.sortOrder, + 'type': typeof data.type !== "undefined" ? data.type : model.type, + 'parentId': typeof data.parentId !== "undefined" ? data.parentId : model.parentId, }); }).then(function (content) { resolve(content); diff --git a/packages/lambda/src/repositories/settings.js b/packages/lambda/src/repositories/settings.js index a191b0f1..a03b90d5 100644 --- a/packages/lambda/src/repositories/settings.js +++ b/packages/lambda/src/repositories/settings.js @@ -61,9 +61,10 @@ SettingsRepository.prototype.populate = function (data) { * Get a Setting * * @param {String} key + * @param {Boolean} returnNull * @return {Promise} */ -SettingsRepository.prototype.get = function (key) { +SettingsRepository.prototype.get = function (key, returnNull = false) { let allModels; return new Promise(function (resolve, reject) { return loadModels().then(function (models) { @@ -74,7 +75,7 @@ SettingsRepository.prototype.get = function (key) { key: key } }).then(function (setting) { - if (setting instanceof allModels.Setting) { + if (setting instanceof allModels.Setting || returnNull) { resolve(setting); } reject(new ResourceNotFoundException('The specified setting does not exist.')); @@ -169,20 +170,23 @@ SettingsRepository.prototype.delete = function (key) { */ SettingsRepository.prototype.batchDeleteByKey = function (models) { let allModels; - const keys = models.forEach(function (model) { - return model.get('key'); + const keys = models.map(function (model) { + return model.key; }); return new Promise(function (resolve, reject) { return loadModels().then(function (models) { allModels = models; }).then(function () { - return allModels.Setting.destroy({ - where: { - key: { - [Sequelize.Op.or]: keys + if (keys.length > 0) { + return allModels.Setting.destroy({ + where: { + key: { + [Sequelize.Op.or]: keys + } } - } - }) + }); + } + resolve(); }).then(function (stuff) { resolve(stuff); }).catch(function (err) { @@ -226,12 +230,10 @@ SettingsRepository.prototype.save = function (model) { return new Promise(function (resolve, reject) { return loadModels().then(function (models) { allModels = models; - if (!(model instanceof allModels.Setting)) { + if (!(model !== null)) { reject(new Error('invalid Setting model')); } return repository.upsert(model, {}); - }).then(function (setting) { - resolve(setting); }).catch(function (err) { reject(err); }).finally(function () { diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index a885a1b5..9f75e2ae 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -49,7 +49,8 @@ SponsorTiersRepository.prototype.populate = function (data) { let allModels; return loadModels().then(function (models) { allModels = models; - return new models.SponsorTier(data); + const sponsorTier = new models.SponsorTier(); + return new sponsorTier.constructor(data, {isNewRecord: typeof data.id === 'undefined'}); }).finally(function () { return allModels.sequelize.close(); }) diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 28a29cd2..142c22a6 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -50,7 +50,8 @@ SponsorsRepository.prototype.populate = function (data) { let allModels; return loadModels().then(function (models) { allModels = models; - return new models.Sponsor(data); + const sponsor = new models.Sponsor(); + return new sponsor.constructor(data, {isNewRecord: typeof data.id === 'undefined'}); }).finally(function () { return allModels.sequelize.close(); }) From 705b14711655825c6231bfc7f33e05a3c89697b8 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 16 Sep 2020 13:20:47 -0500 Subject: [PATCH 069/140] GD-1645: WIP --- .../pages/toolkit/DeleteResourceModal.vue | 2 +- .../admin/pages/toolkit/EditResourceModal.vue | 2 +- .../admin/pages/toolkit/ToolkitListTable.vue | 2 +- packages/lambda/src/api/deleteFiles/index.js | 4 +- .../lambda/src/api/deleteSponsors/index.js | 2 +- .../lambda/src/repositories/repository.js | 6 +-- .../lambda/src/repositories/sponsorTiers.js | 12 ++--- packages/lambda/src/repositories/sponsors.js | 48 +++++++++++++++---- 8 files changed, 55 insertions(+), 23 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/DeleteResourceModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/DeleteResourceModal.vue index 289fa286..7d885913 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/DeleteResourceModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/DeleteResourceModal.vue @@ -81,7 +81,7 @@ } promise.then(function () { - return vue.$request.delete('contents/' + vue.data.content.uuid); + return vue.$request.delete('contents/' + vue.data.content.id); }).then(function () { vue.bus.$emit('deleteToolkitResourceList', vue.data.content); vue.clearModals(); diff --git a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/EditResourceModal.vue b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/EditResourceModal.vue index 5b842e77..53a6e270 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/EditResourceModal.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/EditResourceModal.vue @@ -332,7 +332,7 @@ }).then(function () { toUpdate.forEach(function (content) { if (content.key === 'TOOLKIT_RESOURCE_LIST_ITEM_FILE') { - content.value = file.uuid; + content.value = file.id; } }); }); diff --git a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/ToolkitListTable.vue b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/ToolkitListTable.vue index 2a015117..49abe88a 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/toolkit/ToolkitListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/toolkit/ToolkitListTable.vue @@ -17,7 +17,7 @@ diff --git a/packages/lambda/src/api/deleteFiles/index.js b/packages/lambda/src/api/deleteFiles/index.js index 57e0ae15..47691b17 100644 --- a/packages/lambda/src/api/deleteFiles/index.js +++ b/packages/lambda/src/api/deleteFiles/index.js @@ -27,6 +27,7 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])).parameters(['files']); const s3 = new S3(); + let fileToDelete; request.validate().then(function () { let promise = Promise.resolve(); request.get('files', []).forEach(function (file) { @@ -37,9 +38,10 @@ exports.handle = function (event, context, callback) { return repository.get(file); } }).then(function (file) { + fileToDelete = file; return s3.deleteObject(process.env.AWS_REGION, process.env.AWS_S3_BUCKET, file.get('path')); }).then(function () { - return repository.delete(file); + return repository.delete(fileToDelete.id); }); }); return promise; diff --git a/packages/lambda/src/api/deleteSponsors/index.js b/packages/lambda/src/api/deleteSponsors/index.js index dee2069d..3f4891db 100644 --- a/packages/lambda/src/api/deleteSponsors/index.js +++ b/packages/lambda/src/api/deleteSponsors/index.js @@ -37,7 +37,7 @@ exports.handle = function (event, context, callback) { }); return promise; }).then(function () { - return repository.batchDelete(sponsors); + return repository.bulkDelete(sponsors); }).then(function () { return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { diff --git a/packages/lambda/src/repositories/repository.js b/packages/lambda/src/repositories/repository.js index 62a8baa6..90361408 100644 --- a/packages/lambda/src/repositories/repository.js +++ b/packages/lambda/src/repositories/repository.js @@ -293,10 +293,10 @@ Repository.prototype.batchDelete = function (models) { allModels = models; }).then(function () { let promise = Promise.resolve(); - promise = promise.then(function () { - models.forEach(function (model) { + models.forEach(function (model) { + promise = promise.then(function () { return model.destroy(); - }) + }); }); return promise; }).then(function (stuff) { diff --git a/packages/lambda/src/repositories/sponsorTiers.js b/packages/lambda/src/repositories/sponsorTiers.js index 9f75e2ae..6f345c9a 100644 --- a/packages/lambda/src/repositories/sponsorTiers.js +++ b/packages/lambda/src/repositories/sponsorTiers.js @@ -72,12 +72,12 @@ SponsorTiersRepository.prototype.get = function (id) { where: { id: id } - }).then(function (sponsorTier) { - if (sponsorTier instanceof allModels.SponsorTier) { - resolve(sponsorTier); - } - reject(new ResourceNotFoundException('The specified sponsorTier does not exist.')); }); + }).then(function (sponsorTier) { + if (sponsorTier instanceof allModels.SponsorTier) { + resolve(sponsorTier); + } + reject(new ResourceNotFoundException('The specified sponsorTier does not exist.')); }).catch(function (err) { reject(err); }).finally(function () { @@ -142,7 +142,7 @@ SponsorTiersRepository.prototype.delete = function (id) { return loadModels().then(function (models) { allModels = models; }).then(function () { - return allModels.Setting.destroy({where: {id: id}}); + return allModels.SponsorTier.destroy({where: {id: id}}); }).then(function () { resolve() }).catch(function (err) { diff --git a/packages/lambda/src/repositories/sponsors.js b/packages/lambda/src/repositories/sponsors.js index 142c22a6..36b9bb69 100644 --- a/packages/lambda/src/repositories/sponsors.js +++ b/packages/lambda/src/repositories/sponsors.js @@ -19,6 +19,7 @@ const RepositoryHelper = require('./../helpers/repository'); const ResourceNotFoundException = require('./../exceptions/resourceNotFound'); const SponsorTiersRepository = require('./sponsorTiers'); const loadModels = require('../models/index'); +const Sequelize = require('sequelize'); /** * SponsorsRepository constructor @@ -75,12 +76,12 @@ SponsorsRepository.prototype.get = function (sponsorTierId, id) { id: id, sponsorTierId: sponsorTierId } - }).then(function (sponsor) { - if (sponsor instanceof allModels.Sponsor) { - resolve(sponsor); - } - reject(new ResourceNotFoundException('The specified sponsor does not exist.')); }); + }).then(function (sponsor) { + if (sponsor instanceof allModels.Sponsor) { + resolve(sponsor); + } + reject(new ResourceNotFoundException('The specified sponsor does not exist.')); }).catch(function (err) { reject(err); }).finally(function () { @@ -187,10 +188,7 @@ SponsorsRepository.prototype.save = function (sponsorTierId, model) { return loadModels().then(function (models) { allModels = models; return sponsorTierRepository.get(sponsorTierId); - }).then(function (sponsorTier) { - if (!sponsorTier instanceof allModels.SponsorTier) { - reject('SponsorTier does not exist!'); - } + }).then(function () { return repository.upsert(model, {}, sponsorTierId); }).then(function (sponsor) { resolve(sponsor); @@ -229,6 +227,38 @@ SponsorsRepository.prototype.batchSave = function (sponsorTierId, models) { }); }; +/** + * {[]} models + * + * @param models + * @return {Promise} + */ +SponsorsRepository.prototype.bulkDelete = function (models) { + let allModels; + const ids = models.map(function (model) { + return model.id; + }); + return new Promise(function (resolve, reject) { + return loadModels().then(function (models) { + allModels = models; + }).then(function () { + return allModels.Sponsor.destroy({ + where: { + id: { + [Sequelize.Op.in]: ids + } + } + }); + }).then(function () { + resolve(); + }).catch(function (err) { + reject(err); + }).finally(function () { + return allModels.sequelize.close(); + }); + }); +}; + /** * Batch delete Sponsors * From 2eb7fb6af8258ca2227ce0cd61e4a2e59113e562 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Wed, 16 Sep 2020 16:13:33 -0500 Subject: [PATCH 070/140] GD-1645: WIP --- .../settings/paymentGateway/PaymentGatewaySettings.vue | 5 +++++ packages/lambda/src/api/postUser/index.js | 6 +++--- .../lambda/src/api/resendUserEmailVerification/index.js | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/settings/paymentGateway/PaymentGatewaySettings.vue b/packages/frontend/src/admin-pages/components/admin/settings/paymentGateway/PaymentGatewaySettings.vue index a0f5c8cc..2a9f13a8 100644 --- a/packages/frontend/src/admin-pages/components/admin/settings/paymentGateway/PaymentGatewaySettings.vue +++ b/packages/frontend/src/admin-pages/components/admin/settings/paymentGateway/PaymentGatewaySettings.vue @@ -303,6 +303,11 @@ keys: Object.keys(vue.formData) }).then(function (response) { vue.settings = response.data; + vue.settings.forEach(function (setting) { + if (setting.key === 'PAYMENT_SPRING_LIVE_MODE' || setting.key === 'TEST_PAYMENTS_DISPLAY') { + setting.value = setting.value !== "0"; + } + }); }); }); }, diff --git a/packages/lambda/src/api/postUser/index.js b/packages/lambda/src/api/postUser/index.js index 5f5344a8..e60b4f41 100644 --- a/packages/lambda/src/api/postUser/index.js +++ b/packages/lambda/src/api/postUser/index.js @@ -39,15 +39,15 @@ exports.handle = function (event, context, callback) { return usersRepository.populate({email: email, cognitoUsername: UUID.v4()}) }).then(function (populatedUser) { user = populatedUser; - return cognito.createUser(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername'), user.get('email')); + return cognito.createUser(process.env.AWS_REGION, userPoolId, user.cognitoUsername, user.email); }).then(function (cognitoUser) { cognitoUser.User.Attributes.forEach(function (attribute) { if (attribute.Name === 'sub') { - user.set('cognitoUuid', attribute.Value); + user.cognitoUuid = attribute.Value; } }); }).then(function () { - return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername'), 'Admin'); + return cognito.assignUserToGroup(process.env.AWS_REGION, userPoolId, user.cognitoUsername, 'Admin'); }).then(function () { return usersRepository.upsert(user, {}); }).then(function () { diff --git a/packages/lambda/src/api/resendUserEmailVerification/index.js b/packages/lambda/src/api/resendUserEmailVerification/index.js index f4ee60b4..6917c15d 100644 --- a/packages/lambda/src/api/resendUserEmailVerification/index.js +++ b/packages/lambda/src/api/resendUserEmailVerification/index.js @@ -28,9 +28,9 @@ exports.handle = function (event, context, callback) { request.validate().then(function () { return repository.get(request.urlParam('user_id')); }).then(function (user) { - return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.get('cognitoUsername'), user.get('email'), true).catch(function (err) { + return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.cognitoUsername, user.email, true).catch(function (err) { if (err.code === 'UserNotFoundException') { - return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.get('cognitoUsername'), user.get('email')); + return cognito.createUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.cognitoUsername, user.email); } else { return Promise.reject(err); } From 5b0a9e34774e826a655513b66b5befe038b1df53 Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Thu, 17 Sep 2020 13:43:11 -0500 Subject: [PATCH 071/140] GD-1646: WIP --- .../src/admin-pages/components/account/UserAccount.vue | 6 +++--- .../components/account/UserAccountInfoModal.vue | 8 ++++---- .../src/admin-pages/components/header/Navigation.vue | 9 +++++---- .../settings/requestNameChange/RequestNameChange.vue | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/account/UserAccount.vue b/packages/frontend/src/admin-pages/components/account/UserAccount.vue index 2e3f3fbf..4d4fa896 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccount.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccount.vue @@ -86,9 +86,9 @@ export default { data: function () { return { - firstName: this.user.firstName || '', - lastName: this.user.lastName || '', - nonprofitUuid: this.user.nonprofitUuid, + firstName: this.user.dataValues.firstName || '', + lastName: this.user.dataValues.lastName || '', + nonprofitUuid: this.user.dataValues.nonprofitUuid, } }, created: function () { diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue index e05b162d..fdd8429a 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue @@ -79,8 +79,8 @@ // Form Data formData: { - firstName: this.user.firstName, - lastName: this.user.lastName + firstName: this.user.dataValues.firstName, + lastName: this.user.dataValues.lastName }, // Errors @@ -139,13 +139,13 @@ return; } - vue.$request.patch('users/' + vue.user.cognitoUsername, params).then(function (response) { + vue.$request.patch('users/' + vue.user.dataValues.cognitoUsername, params).then(function (response) { vue.removeModal(); if (response.data.errorMessage) { console.log(response.data); } else { vue.clearModals(); - vue.bus.$emit('userAccountUpdateInfo', response.data); + vue.bus.$emit('userAccountUpdateInfo', response.data[0]); } }).catch(function (err) { vue.removeModal(); diff --git a/packages/frontend/src/admin-pages/components/header/Navigation.vue b/packages/frontend/src/admin-pages/components/header/Navigation.vue index b103b7ad..36bb06a1 100644 --- a/packages/frontend/src/admin-pages/components/header/Navigation.vue +++ b/packages/frontend/src/admin-pages/components/header/Navigation.vue @@ -29,7 +29,7 @@
- +
@@ -68,9 +68,10 @@ export default { data: function () { return { - firstName: this.user.firstName, - lastName: this.user.lastName, - gravatarAlt: this.user.firstName && this.user.lastName ? this.user.firstName + ' ' + this.user.lastName : 'Avatar', + firstName: this.user.dataValues.firstName, + lastName: this.user.dataValues.lastName, + email: this.user.dataValues.email, + gravatarAlt: this.user.dataValues.firstName && this.user.dataValues.lastName ? this.user.dataValues.firstName + ' ' + this.user.dataValues.lastName : 'Avatar', navigationComponent: 'navigation-nonprofit', displayingMenu: false, diff --git a/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue b/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue index 2bb31338..bd6ecfb8 100644 --- a/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue +++ b/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue @@ -149,10 +149,10 @@ submitRequest: function () { const vue = this; - const name = (vue.user.firstName && vue.user.lastName) ? vue.user.firstName + ' ' + vue.user.lastName : vue.nonprofit.legalName; + const name = (vue.user.dataValues.firstName && vue.user.dataValues.lastName) ? vue.user.dataValues.firstName + ' ' + vue.user.dataValues.lastName : vue.nonprofit.legalName; vue.$request.post('messages', { name: name, - email: vue.user.email, + email: vue.user.dataValues.email, message: vue.formatMessage(), type: 'NAME_CHANGE' }).then(function () { From 202364da09c898c3b13e35eda294af06210ed10c Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Fri, 18 Sep 2020 08:37:28 -0500 Subject: [PATCH 072/140] GD-1646: WIP --- .../admin-pages/components/account/UserAccountPasswordModal.vue | 2 +- .../components/auth/forgotPassword/ForgotPasswordResetForm.vue | 2 +- .../src/admin-pages/components/auth/login/PasswordResetForm.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue index ee063f09..1240a881 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue @@ -69,7 +69,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters. + Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters.
diff --git a/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue b/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue index 90344e27..024bb66e 100644 --- a/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue +++ b/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue @@ -67,7 +67,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters. + Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters.
diff --git a/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue b/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue index 5c3c7b53..23e6d051 100644 --- a/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue +++ b/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue @@ -46,7 +46,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters. + Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters.
From 0690240f09910ccb1a43334a620962dbde2d5e8f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Fri, 18 Sep 2020 13:54:19 -0500 Subject: [PATCH 073/140] GD-1646: WIP --- .../src/admin-pages/components/account/UserAccount.vue | 6 +++--- .../components/account/UserAccountInfoModal.vue | 6 +++--- .../components/account/UserAccountPasswordModal.vue | 2 +- .../admin/sponsorTiers/sponsors/SponsorsListTable.vue | 2 +- .../auth/forgotPassword/ForgotPasswordResetForm.vue | 2 +- .../components/auth/login/PasswordResetForm.vue | 2 +- .../src/admin-pages/components/header/Navigation.vue | 8 ++++---- .../settings/requestNameChange/RequestNameChange.vue | 4 ++-- packages/lambda/src/api/deleteUser/index.js | 4 +++- packages/lambda/src/api/getUserProfile/index.js | 2 +- packages/lambda/src/api/getUsers/index.js | 4 ++-- packages/lambda/src/api/patchSponsorTier/index.js | 2 +- 12 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/account/UserAccount.vue b/packages/frontend/src/admin-pages/components/account/UserAccount.vue index 4d4fa896..2e3f3fbf 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccount.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccount.vue @@ -86,9 +86,9 @@ export default { data: function () { return { - firstName: this.user.dataValues.firstName || '', - lastName: this.user.dataValues.lastName || '', - nonprofitUuid: this.user.dataValues.nonprofitUuid, + firstName: this.user.firstName || '', + lastName: this.user.lastName || '', + nonprofitUuid: this.user.nonprofitUuid, } }, created: function () { diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue index fdd8429a..d711656d 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountInfoModal.vue @@ -79,8 +79,8 @@ // Form Data formData: { - firstName: this.user.dataValues.firstName, - lastName: this.user.dataValues.lastName + firstName: this.user.firstName, + lastName: this.user.lastName }, // Errors @@ -139,7 +139,7 @@ return; } - vue.$request.patch('users/' + vue.user.dataValues.cognitoUsername, params).then(function (response) { + vue.$request.patch('users/' + vue.user.cognitoUsername, params).then(function (response) { vue.removeModal(); if (response.data.errorMessage) { console.log(response.data); diff --git a/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue b/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue index 1240a881..ee063f09 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccountPasswordModal.vue @@ -69,7 +69,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters. + Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters.
diff --git a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue index 0db6af5f..7ab51d88 100644 --- a/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue +++ b/packages/frontend/src/admin-pages/components/admin/sponsorTiers/sponsors/SponsorsListTable.vue @@ -64,7 +64,7 @@ } }, sponsorTierId: { - type: String, + type: String|Number, default: null, } }, diff --git a/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue b/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue index 024bb66e..90344e27 100644 --- a/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue +++ b/packages/frontend/src/admin-pages/components/auth/forgotPassword/ForgotPasswordResetForm.vue @@ -67,7 +67,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters. + Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters.
diff --git a/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue b/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue index 23e6d051..5c3c7b53 100644 --- a/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue +++ b/packages/frontend/src/admin-pages/components/auth/login/PasswordResetForm.vue @@ -46,7 +46,7 @@ {{ formErrors.password }}
- Your password must be at least 8 characters long with a combination of numbers, uppercase letters, and lowercase letters. + Your password must be at least 8 characters long and contain a combination of numbers and upper and lower case letters.
diff --git a/packages/frontend/src/admin-pages/components/header/Navigation.vue b/packages/frontend/src/admin-pages/components/header/Navigation.vue index 36bb06a1..eac6d652 100644 --- a/packages/frontend/src/admin-pages/components/header/Navigation.vue +++ b/packages/frontend/src/admin-pages/components/header/Navigation.vue @@ -68,10 +68,10 @@ export default { data: function () { return { - firstName: this.user.dataValues.firstName, - lastName: this.user.dataValues.lastName, - email: this.user.dataValues.email, - gravatarAlt: this.user.dataValues.firstName && this.user.dataValues.lastName ? this.user.dataValues.firstName + ' ' + this.user.dataValues.lastName : 'Avatar', + firstName: this.user.firstName, + lastName: this.user.lastName, + email: this.user.email, + gravatarAlt: this.user.firstName && this.user.lastName ? this.user.firstName + ' ' + this.user.lastName : 'Avatar', navigationComponent: 'navigation-nonprofit', displayingMenu: false, diff --git a/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue b/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue index bd6ecfb8..2bb31338 100644 --- a/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue +++ b/packages/frontend/src/admin-pages/components/nonprofit/settings/requestNameChange/RequestNameChange.vue @@ -149,10 +149,10 @@ submitRequest: function () { const vue = this; - const name = (vue.user.dataValues.firstName && vue.user.dataValues.lastName) ? vue.user.dataValues.firstName + ' ' + vue.user.dataValues.lastName : vue.nonprofit.legalName; + const name = (vue.user.firstName && vue.user.lastName) ? vue.user.firstName + ' ' + vue.user.lastName : vue.nonprofit.legalName; vue.$request.post('messages', { name: name, - email: vue.user.dataValues.email, + email: vue.user.email, message: vue.formatMessage(), type: 'NAME_CHANGE' }).then(function () { diff --git a/packages/lambda/src/api/deleteUser/index.js b/packages/lambda/src/api/deleteUser/index.js index 24bd542f..ccd63dd6 100644 --- a/packages/lambda/src/api/deleteUser/index.js +++ b/packages/lambda/src/api/deleteUser/index.js @@ -26,7 +26,9 @@ exports.handle = function (event, context, callback) { const request = new Request(event, context).middleware(new UserGroupMiddleware(['SuperAdmin', 'Admin'])); request.validate().then(function () { - return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, request.urlParam('user_id')); + return repository.get(request.urlParam('user_id')) + }).then(function (user) { + return cognito.deleteUser(process.env.AWS_REGION, process.env.USER_POOL_ID, user.cognitoUsername); }).then(function () { return repository.delete(request.urlParam('user_id')); }).then(function () { diff --git a/packages/lambda/src/api/getUserProfile/index.js b/packages/lambda/src/api/getUserProfile/index.js index f5277b03..c7188eed 100644 --- a/packages/lambda/src/api/getUserProfile/index.js +++ b/packages/lambda/src/api/getUserProfile/index.js @@ -31,7 +31,7 @@ exports.handle = function (event, context, callback) { } }).then(function (user) { const groups = request.user().groups || []; - callback(null, _.merge({}, user, {groups: groups})); + callback(null, _.merge({}, user.get(), {groups: groups})); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); diff --git a/packages/lambda/src/api/getUsers/index.js b/packages/lambda/src/api/getUsers/index.js index 08eeaf9c..92913f50 100644 --- a/packages/lambda/src/api/getUsers/index.js +++ b/packages/lambda/src/api/getUsers/index.js @@ -36,9 +36,9 @@ exports.handle = function (event, context, callback) { let result = user; promise = promise.then(function () { return cognito.listGroupsForUser(process.env.AWS_REGION, userPoolId, user.get('cognitoUsername')).then(function (response) { - result.setDataValue('groups', response.hasOwnProperty('Groups') ? response.Groups.map(function (group) { + result.groups = response.hasOwnProperty('Groups') ? response.Groups.map(function (group) { return group.GroupName; - }) : []); + }) : []; results.push(result); }); }); diff --git a/packages/lambda/src/api/patchSponsorTier/index.js b/packages/lambda/src/api/patchSponsorTier/index.js index eb5ccbff..8215b3ce 100644 --- a/packages/lambda/src/api/patchSponsorTier/index.js +++ b/packages/lambda/src/api/patchSponsorTier/index.js @@ -34,7 +34,7 @@ exports.handle = function (event, context, callback) { sponsorTier = response; return lambda.invoke(process.env.AWS_REGION, process.env.AWS_STACK_NAME + '-ApiGatewayFlushCache', {}, 'RequestResponse'); }).then(function () { - callback(null, sponsorTier.all()); + callback(null, sponsorTier); }).catch(function (err) { (err instanceof HttpException) ? callback(err.context(context)) : callback(err); }); From 34b45a29321ff8679050e83a95643b6edfcc208f Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Mon, 21 Sep 2020 22:35:09 +0000 Subject: [PATCH 074/140] fix: packages/frontend/package.json & packages/frontend/package-lock.json to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-UAPARSERJS-610226 --- packages/frontend/package-lock.json | 799 +++++++++++++++++----------- packages/frontend/package.json | 2 +- 2 files changed, 503 insertions(+), 298 deletions(-) diff --git a/packages/frontend/package-lock.json b/packages/frontend/package-lock.json index f4e0cf7c..43a55551 100644 --- a/packages/frontend/package-lock.json +++ b/packages/frontend/package-lock.json @@ -2577,7 +2577,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -2762,16 +2763,16 @@ "dev": true }, "browser-sync": { - "version": "2.26.7", - "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.7.tgz", - "integrity": "sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w==", + "version": "2.26.9", + "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.9.tgz", + "integrity": "sha512-W6gj+Ok2WhVJE0rN3HOjzBtwrES7YnoQ9JMF7MtRmkDIUWc7ACc4UQDvHLH7+Q7F1eMVntmpF5NP/bb9gNbwvQ==", "dev": true, "requires": { - "browser-sync-client": "^2.26.6", - "browser-sync-ui": "^2.26.4", + "browser-sync-client": "^2.26.9", + "browser-sync-ui": "^2.26.9", "bs-recipes": "1.3.4", "bs-snippet-injector": "^2.0.1", - "chokidar": "^2.0.4", + "chokidar": "^3.4.1", "connect": "3.6.6", "connect-history-api-fallback": "^1", "dev-ip": "^1.0.1", @@ -2780,10 +2781,10 @@ "etag": "^1.8.1", "fresh": "^0.5.2", "fs-extra": "3.0.1", - "http-proxy": "1.15.2", + "http-proxy": "^1.18.1", "immutable": "^3", - "localtunnel": "1.9.2", - "micromatch": "^3.1.10", + "localtunnel": "^2.0.0", + "micromatch": "^4.0.2", "opn": "5.3.0", "portscanner": "2.1.1", "qs": "6.2.3", @@ -2795,25 +2796,131 @@ "serve-static": "1.13.2", "server-destroy": "1.0.1", "socket.io": "2.1.1", - "ua-parser-js": "0.7.17", - "yargs": "6.4.0" + "ua-parser-js": "^0.7.18", + "yargs": "^15.4.1" }, "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "opn": { "version": "5.3.0", - "resolved": "http://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, "requires": { "is-wsl": "^1.1.0" } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "browser-sync-client": { - "version": "2.26.6", - "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.6.tgz", - "integrity": "sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw==", + "version": "2.26.12", + "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.12.tgz", + "integrity": "sha512-bEBDRkufKxrIfjOsIB1FN9itUEXr2oLtz1AySgSSr80K2AWzmtoYnxtVASx/i40qFrSdeI31pNvdCjHivihLVA==", "dev": true, "requires": { "etag": "1.8.1", @@ -2829,9 +2936,9 @@ "dev": true }, "browser-sync-ui": { - "version": "2.26.4", - "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz", - "integrity": "sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA==", + "version": "2.26.12", + "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.12.tgz", + "integrity": "sha512-PkAJNf/TfCFTCkQUfXplR2Kp/+/lbCWFO9lrgLZsmxIhvMLx2pYZFBbTBIaem8qjXhld9ZcESUC8EdU5VWFJgQ==", "dev": true, "requires": { "async-each-series": "0.1.1", @@ -3416,14 +3523,68 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } } }, "coa": { @@ -4904,12 +5065,12 @@ } }, "engine.io-client": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", - "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.3.tgz", + "integrity": "sha512-0NGY+9hioejTEJCaSJZfWZLk4FPI9dN+1H1C4+wj2iuFba47UgZbJzfWs4aNFajnX/qAaYKbe2lLTfEEWzCmcw==", "dev": true, "requires": { - "component-emitter": "1.2.1", + "component-emitter": "~1.3.0", "component-inherit": "0.0.3", "debug": "~4.1.0", "engine.io-parser": "~2.2.0", @@ -4922,6 +5083,12 @@ "yeast": "0.1.2" }, "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -5118,9 +5285,9 @@ "dev": true }, "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, "events": { @@ -5389,7 +5556,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -6545,12 +6713,6 @@ "parse-passwd": "^1.0.0" } }, - "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", - "dev": true - }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -6719,13 +6881,14 @@ "dev": true }, "http-proxy": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.15.2.tgz", - "integrity": "sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE=", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { - "eventemitter3": "1.x.x", - "requires-port": "1.x.x" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" } }, "http-proxy-middleware": { @@ -7413,12 +7576,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -7673,12 +7830,6 @@ "has-symbols": "^1.0.0" } }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -7827,15 +7978,6 @@ "is-buffer": "^1.1.5" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -7847,24 +7989,11 @@ } }, "limiter": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz", - "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", "dev": true }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -7883,21 +8012,21 @@ } }, "localtunnel": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.2.tgz", - "integrity": "sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.0.tgz", + "integrity": "sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg==", "dev": true, "requires": { "axios": "0.19.0", "debug": "4.1.1", "openurl": "1.1.1", - "yargs": "6.6.0" + "yargs": "13.3.0" }, "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "debug": { @@ -7909,31 +8038,109 @@ "ms": "^2.1.1" } }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, "yargs": { - "version": "6.6.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" } } } @@ -8274,9 +8481,9 @@ } }, "mitt": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.1.3.tgz", - "integrity": "sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", "dev": true }, "mixin-deep": { @@ -8508,35 +8715,6 @@ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -8878,15 +9056,6 @@ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -8978,15 +9147,6 @@ "safe-buffer": "^5.1.1" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -9081,17 +9241,6 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -12213,48 +12362,6 @@ "pify": "^2.3.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", @@ -13283,7 +13390,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -13405,9 +13513,9 @@ } }, "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", "dev": true }, "socket.io-client": { @@ -13590,38 +13698,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, "spdy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", @@ -14208,15 +14284,6 @@ "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -14905,9 +14972,9 @@ "dev": true }, "ua-parser-js": { - "version": "0.7.17", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", - "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==", + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", + "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", "dev": true }, "uglify-js": { @@ -15206,16 +15273,6 @@ "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "validate.js": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.10.0.tgz", @@ -16328,15 +16385,9 @@ } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "word-wrap": { @@ -16443,48 +16494,202 @@ "dev": true }, "yargs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz", - "integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.1.0" + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "camelcase": "^3.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "dependencies": { "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true } } diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 331513d7..2dbfa0e1 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -45,7 +45,7 @@ "aws-sdk": "^2.336.0", "axios": "^0.19.0", "babel-loader": "^8.0.4", - "browser-sync": "^2.26.7", + "browser-sync": "^2.26.9", "browser-sync-middleware-spa": "^1.0.0", "browser-sync-webpack-plugin": "^2.2.2", "chosen-js": "^1.8.2", From 0ccf763d7ec3a98dc1c9b38ee2f9cee27683e58b Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Fri, 25 Sep 2020 10:44:13 -0500 Subject: [PATCH 075/140] GD-1646: WIP --- .../components/admin/pages/custom/CustomPagesEdit.vue | 2 +- packages/lambda/migrations/00_initial.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue index 3d733a39..b20fe885 100644 --- a/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue +++ b/packages/frontend/src/admin-pages/components/admin/pages/custom/CustomPagesEdit.vue @@ -222,7 +222,7 @@ } if (!vm.isEditingSlug) { - vm.formData.PAGE_SLUG.value = slug(vm.formData.PAGE_TITLE.value, {lower: true}); + vm.formData.PAGE_SLUG.value = vm.formData.PAGE_SLUG.value !== vm.formData.PAGE_TITLE.value ? slug(vm.formData.PAGE_SLUG.value, {lower: true}) : slug(vm.formData.PAGE_TITLE.value, {lower: true}); } }, deep: true diff --git a/packages/lambda/migrations/00_initial.js b/packages/lambda/migrations/00_initial.js index d9bc8f7a..1d7251cc 100644 --- a/packages/lambda/migrations/00_initial.js +++ b/packages/lambda/migrations/00_initial.js @@ -650,7 +650,7 @@ module.exports = { primaryKey: true }, key: { - type: Sequelize.STRING(50), + type: Sequelize.STRING(2048), allowNull: false }, value: { From dfa12531dd9119b9211c2f2500b270c8b22e1d2f Mon Sep 17 00:00:00 2001 From: dylanmmatthews Date: Tue, 29 Sep 2020 15:55:58 -0500 Subject: [PATCH 076/140] GD-1651: Update Nonprofit Repository --- .../templates/givesource-api-deploy.yml | 2 +- .../templates/givesource-api-nonprofits.yml | 253 +++++++++++++++--- .../cloudformation/templates/givesource.yml | 1 + .../components/account/UserAccount.vue | 2 +- .../admin/nonprofits/NonprofitsList.vue | 8 +- .../admin/nonprofits/NonprofitsListTable.vue | 4 +- .../nonprofits/NonprofitsListTableRow.vue | 16 +- .../admin/nonprofits/RevokeNonprofitModal.vue | 2 +- .../manageAdmins/ManageAdminsListTable.vue | 2 +- .../components/header/Navigation.vue | 8 +- .../header/NavigationNonprofits.vue | 8 +- .../nonprofit/donations/DonationsList.vue | 2 +- .../donations/DonationsListTableHeader.vue | 2 +- .../nonprofit/settings/SettingsList.vue | 2 +- .../DonationNotifications.vue | 10 +- .../settings/manageAdmins/ManageAdmins.vue | 10 +- .../manageAdmins/ManageAdminsInvite.vue | 10 +- .../manageAdmins/ManageAdminsListTable.vue | 10 +- .../manageAdmins/ManageAdminsListTableRow.vue | 2 +- .../manageOrganization/ManageOrganization.vue | 10 +- .../requestNameChange/RequestNameChange.vue | 8 +- .../settings/socialSharing/SocialSharing.vue | 10 +- .../nonprofit/yourPage/YourPage.vue | 10 +- .../yourPage/media/MediaListTableRow.vue | 2 +- .../nonprofit/yourPage/media/PhotosEdit.vue | 28 +- .../nonprofit/yourPage/media/VideosAdd.vue | 12 +- .../nonprofit/yourPage/media/VideosEdit.vue | 14 +- .../nonprofit/yourPage/tabs/Content.vue | 2 +- .../nonprofit/yourPage/tabs/DonationTiers.vue | 2 +- .../nonprofit/yourPage/tabs/Media.vue | 32 +-- .../frontend/src/admin-pages/router/index.js | 58 ++-- .../public-pages/components/layout/Header.vue | 2 +- .../components/nonprofits/Nonprofit.vue | 2 +- .../frontend/src/public-pages/router/index.js | 4 +- .../frontend/src/public-pages/store/index.js | 2 +- packages/lambda/migrations/00_initial.js | 66 ++++- .../src/api/adminRegisterNonprofit/index.js | 32 +-- .../lambda/src/api/deleteNonprofit/index.js | 2 +- .../src/api/deleteNonprofitDonation/index.js | 2 +- .../api/deleteNonprofitDonationTiers/index.js | 4 +- .../src/api/deleteNonprofitSlide/index.js | 6 +- .../src/api/deleteNonprofitUser/index.js | 2 +- packages/lambda/src/api/getNonprofit/index.js | 4 +- .../src/api/getNonprofitDonation/index.js | 4 +- .../src/api/getNonprofitDonationTier/index.js | 2 +- .../api/getNonprofitDonationTiers/index.js | 2 +- .../src/api/getNonprofitDonations/index.js | 4 +- .../src/api/getNonprofitReport/index.js | 4 +- .../lambda/src/api/getNonprofitSlide/index.js | 4 +- .../src/api/getNonprofitSlides/index.js | 7 +- .../lambda/src/api/getNonprofitUsers/index.js | 4 +- .../lambda/src/api/getNonprofits/index.js | 46 +--- .../lambda/src/api/patchNonprofit/index.js | 13 +- .../src/api/patchNonprofitDonation/index.js | 4 +- .../api/patchNonprofitDonationTiers/index.js | 6 +- .../src/api/patchNonprofitSlide/index.js | 6 +- .../src/api/patchNonprofitSlides/index.js | 4 +- .../src/api/patchNonprofitStatus/index.js | 4 +- .../lambda/src/api/postNonprofit/index.js | 7 +- .../src/api/postNonprofitDonation/index.js | 6 +- .../api/postNonprofitDonationTier/index.js | 6 +- .../src/api/postNonprofitReport/index.js | 6 +- .../src/api/postNonprofitSlide/index.js | 18 +- .../lambda/src/api/postNonprofitUser/index.js | 4 +- .../lambda/src/api/registerNonprofit/index.js | 27 +- .../src/middleware/nonprofitResource.js | 10 +- packages/lambda/src/models/index.js | 23 ++ packages/lambda/src/models/nonprofit.js | 135 ++++++++++ .../src/models/nonprofitDonationTier.js | 44 +++ packages/lambda/src/models/nonprofitSlide.js | 73 +++++ .../src/repositories/nonprofitSlides.js | 205 +++++++++----- .../lambda/src/repositories/nonprofits.js | 199 +++++++++++--- packages/lambda/src/repositories/users.js | 16 +- 73 files changed, 1114 insertions(+), 449 deletions(-) create mode 100644 packages/lambda/src/models/nonprofit.js create mode 100644 packages/lambda/src/models/nonprofitDonationTier.js create mode 100644 packages/lambda/src/models/nonprofitSlide.js diff --git a/packages/cloudformation/templates/givesource-api-deploy.yml b/packages/cloudformation/templates/givesource-api-deploy.yml index fc417fd5..b084edb1 100644 --- a/packages/cloudformation/templates/givesource-api-deploy.yml +++ b/packages/cloudformation/templates/givesource-api-deploy.yml @@ -64,7 +64,7 @@ Resources: CacheDataEncrypted: true CacheTtlInSeconds: 60 CachingEnabled: true - - ResourcePath: "/nonprofits/{nonprofit_uuid}" + - ResourcePath: "/nonprofits/{nonprofit_id}" HttpMethod: GET CacheDataEncrypted: true CacheTtlInSeconds: 60 diff --git a/packages/cloudformation/templates/givesource-api-nonprofits.yml b/packages/cloudformation/templates/givesource-api-nonprofits.yml index 9fc0d7f0..ea89b5c7 100644 --- a/packages/cloudformation/templates/givesource-api-nonprofits.yml +++ b/packages/cloudformation/templates/givesource-api-nonprofits.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -47,7 +50,7 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofit.zip - Description: "Get a nonprofit by uuid" + Description: "Get a nonprofit by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName @@ -58,6 +61,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -66,7 +75,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id} DependsOn: GetNonprofitLambdaFunction GetNonprofitsLambdaFunction: @@ -87,6 +96,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -116,6 +131,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -145,6 +166,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -153,7 +180,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id} DependsOn: PatchNonprofitLambdaFunction DeleteNonprofitLambdaFunction: @@ -174,6 +201,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -182,7 +215,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id} DependsOn: DeleteNonprofitLambdaFunction # Nonprofit Donations Lambda Resources @@ -194,7 +227,7 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofitDonation.zip - Description: "Get a nonprofit's donation by uuid" + Description: "Get a nonprofit's donation by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName @@ -205,6 +238,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -213,7 +252,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/donations/{donation_uuid} DependsOn: GetNonprofitDonationLambdaFunction GetNonprofitDonationsLambdaFunction: @@ -234,6 +273,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -242,7 +287,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/donations + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/donations DependsOn: GetNonprofitDonationsLambdaFunction PostNonprofitDonationLambdaFunction: @@ -263,6 +308,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -271,7 +322,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/donations + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/donations DependsOn: PostNonprofitDonationLambdaFunction PatchNonprofitDonationLambdaFunction: @@ -292,6 +343,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -300,7 +357,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/donations/{donation_uuid} DependsOn: PatchNonprofitDonationLambdaFunction DeleteNonprofitDonationLambdaFunction: @@ -321,6 +378,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -329,7 +392,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/donations/{donation_uuid} DependsOn: DeleteNonprofitDonationLambdaFunction # Nonprofit Donation Tiers Lambda Resources @@ -352,6 +415,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -360,7 +429,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/tiers/{donation_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/tiers/{donation_tier_uuid} DependsOn: GetNonprofitDonationTierLambdaFunction GetNonprofitDonationTiersLambdaFunction: @@ -381,6 +450,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -389,7 +464,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/tiers DependsOn: GetNonprofitDonationTiersLambdaFunction PostNonprofitDonationTierLambdaFunction: @@ -410,6 +485,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitDonationTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -418,7 +499,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/tiers DependsOn: PostNonprofitDonationTierLambdaFunction PatchNonprofitDonationTiersLambdaFunction: @@ -439,6 +520,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -447,7 +534,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/tiers DependsOn: PatchNonprofitDonationTiersLambdaFunction DeleteNonprofitDonationTiersLambdaFunction: @@ -468,6 +555,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -476,7 +569,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/tiers DependsOn: DeleteNonprofitDonationTiersLambdaFunction # Nonprofit Pages Lambda Resources @@ -488,7 +581,7 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofitPage.zip - Description: "Get a nonprofit by uuid" + Description: "Get a nonprofit by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName @@ -499,6 +592,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitPageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -530,6 +629,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -538,7 +643,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/reports/{report_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/reports/{report_uuid} DependsOn: GetNonprofitReportLambdaFunction PostNonprofitReportLambdaFunction: @@ -559,6 +664,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -567,7 +678,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/reports + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/reports DependsOn: PostNonprofitReportLambdaFunction # Nonprofit Slides Lambda Resources @@ -590,6 +701,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -598,7 +715,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: GetNonprofitSlideLambdaFunction GetNonprofitSlidesLambdaFunction: @@ -619,6 +736,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitSlidesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -627,7 +750,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/slides DependsOn: GetNonprofitSlidesLambdaFunction PostNonprofitSlideLambdaFunction: @@ -648,6 +771,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -656,7 +785,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/slides DependsOn: PostNonprofitSlideLambdaFunction PatchNonprofitSlideLambdaFunction: @@ -677,6 +806,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -685,7 +820,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: PatchNonprofitSlideLambdaFunction PatchNonprofitSlidesLambdaFunction: @@ -706,6 +841,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitSlidesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -714,7 +855,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/slides DependsOn: PatchNonprofitSlidesLambdaFunction DeleteNonprofitSlideLambdaFunction: @@ -736,6 +877,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -744,7 +891,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: PatchNonprofitSlideLambdaFunction # Nonprofit Users Lambda Resources @@ -767,6 +914,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitUsersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -775,7 +928,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/users + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/users DependsOn: GetNonprofitUsersLambdaFunction PostNonprofitUserLambdaFunction: @@ -797,6 +950,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -805,7 +964,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/users + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/users DependsOn: PostNonprofitUserLambdaFunction DeleteNonprofitUserLambdaFunction: @@ -827,6 +986,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -835,7 +1000,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/users/{user_id} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/users/{user_id} DependsOn: DeleteNonprofitUserLambdaFunction # Nonprofit Admin Lambda Resources @@ -859,6 +1024,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet NonprofitAdminRegisterLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -890,6 +1061,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet NonprofitRegisterLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -921,6 +1098,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SearchNonprofitsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -953,6 +1136,12 @@ Resources: Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitStatusLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -961,7 +1150,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/status + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/status DependsOn: PatchNonprofitStatusLambdaFunction # Nonprofits Api Gateway Resources @@ -978,7 +1167,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitsApiResource - PathPart: "{nonprofit_uuid}" + PathPart: "{nonprofit_id}" GetNonprofitApiMethod: Type: AWS::ApiGateway::Method @@ -990,14 +1179,14 @@ Resources: ApiKeyRequired: false RequestParameters: method.request.querystring.c: false - method.request.path.nonprofit_uuid: true + method.request.path.nonprofit_id: true Integration: Type: AWS IntegrationHttpMethod: POST PassthroughBehavior: NEVER CacheKeyParameters: - method.request.querystring.c - - method.request.path.nonprofit_uuid + - method.request.path.nonprofit_id RequestTemplates: application/json: !Ref IntegrationRequestTemplate Uri: !Sub @@ -2643,7 +2832,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitSlidesApiResource - PathPart: "{slide_uuid}" + PathPart: "{slide_id}" GetNonprofitSlideApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index ae987cd5..322609b6 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -559,6 +559,7 @@ Resources: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] diff --git a/packages/frontend/src/admin-pages/components/account/UserAccount.vue b/packages/frontend/src/admin-pages/components/account/UserAccount.vue index 2e3f3fbf..61b0fbed 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccount.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccount.vue @@ -16,7 +16,7 @@ @@ -83,14 +83,14 @@ return this.isSuperAdminUser() || this.isAdminUser(); }, logoLink: function () { - if (!this.isAdmin && this.nonprofitUuid) { - return {name: 'nonprofit-donations-list', params: {nonprofitUuid: this.nonprofitUuid}}; + if (!this.isAdmin && this.nonprofitId) { + return {name: 'nonprofit-donations-list', params: {nonprofitId: this.nonprofitId}}; } return {name: 'donations-list'}; } }, props: [ - 'nonprofitUuid' + 'nonprofitId' ], created: function () { const vue = this; diff --git a/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue b/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue index 38e1280a..df28c772 100644 --- a/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue +++ b/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue @@ -18,13 +18,13 @@
@@ -50,7 +50,7 @@ this.setSelected(); }, props: [ - 'nonprofitUuid' + 'nonprofitId' ], methods: { setSelected: function () { diff --git a/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue b/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue index 3a9ab559..54b46de4 100644 --- a/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue +++ b/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue @@ -16,7 +16,7 @@