From ae8e84deb6656a6fb951ad0bdefb5d45bb0e2470 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 5 Feb 2022 01:24:23 +0100 Subject: [PATCH 01/67] =?UTF-8?q?=F0=9F=9A=80=20crowdaction=20hex=20refact?= =?UTF-8?q?oring=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/models/crowdaction.go | 13 +++++++ pkg/handler/aws/crowdaction/README.md | 0 pkg/handler/aws/crowdaction/main.go | 51 +++++++++++++++++++++++++++ pkg/handler/aws/emailContact/main.go | 6 +++- 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 internal/models/crowdaction.go create mode 100644 pkg/handler/aws/crowdaction/README.md create mode 100644 pkg/handler/aws/crowdaction/main.go diff --git a/internal/models/crowdaction.go b/internal/models/crowdaction.go new file mode 100644 index 0000000..7cf360a --- /dev/null +++ b/internal/models/crowdaction.go @@ -0,0 +1,13 @@ +package models + +type CrowdActionRequest struct { + Title string + Description string + AppVersion string +} + +type CrowdAction struct { + CrowdactionID string + Title string + Description string +} diff --git a/pkg/handler/aws/crowdaction/README.md b/pkg/handler/aws/crowdaction/README.md new file mode 100644 index 0000000..e69de29 diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go new file mode 100644 index 0000000..556aa79 --- /dev/null +++ b/pkg/handler/aws/crowdaction/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + + "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/aws/aws-lambda-go/events" + "github.com/aws/aws-lambda-go/lambda" + "github.com/go-playground/validator/v10" +) + +var ( + tableName = os.Getenv("TABLE_NAME") +) + +func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { + fmt.Println("Entering the crowdaction endpoint") + + // invoking crowdaction model + var request models.CrowdActionRequest + + // creating a new validator object + validate := validator.New() + + // validating against error + if err := validate.StructCtx(ctx, request); err != nil { + return errToResponse(err, http.StatusBadRequest), nil + } + + // AWS session + //sess := session.Must(session.NewSession()) + + if err := json.Unmarshal([]byte(req.Body), &request); err != nil { + return errToResponse(err, http.StatusBadRequest), nil + } + + return events.APIGatewayV2HTTPResponse{StatusCode: 200, Body: "Success!"}, nil +} + +func main() { + lambda.Start(handler) +} + +func errToResponse(err error, code int) events.APIGatewayV2HTTPResponse { + msg, _ := json.Marshal(map[string]string{"message": err.Error()}) + return events.APIGatewayV2HTTPResponse{Body: string(msg), StatusCode: code} +} diff --git a/pkg/handler/aws/emailContact/main.go b/pkg/handler/aws/emailContact/main.go index 97059ce..2a18144 100644 --- a/pkg/handler/aws/emailContact/main.go +++ b/pkg/handler/aws/emailContact/main.go @@ -3,6 +3,9 @@ package main import ( "context" "encoding/json" + "fmt" + "net/http" + "github.com/CollActionteam/collaction_backend/internal/contact" "github.com/CollActionteam/collaction_backend/internal/models" awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" @@ -10,7 +13,6 @@ import ( "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go/aws/session" "github.com/go-playground/validator/v10" - "net/http" ) func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { @@ -19,6 +21,8 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP return errToResponse(err, http.StatusBadRequest), nil } + fmt.Println("Hello World") + validate := validator.New() if err := validate.StructCtx(ctx, request); err != nil { //TODO 10.01.22 mrsoftware: fix the error message From ac8387fd4e7d0b90f8791e93be78071295c63779 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 5 Feb 2022 13:23:37 +0100 Subject: [PATCH 02/67] =?UTF-8?q?=F0=9F=9A=A7=20=20dynamodb=20manager=20re?= =?UTF-8?q?pository,=20pt1:=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/repository/aws/dynamoManager.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 pkg/repository/aws/dynamoManager.go diff --git a/pkg/repository/aws/dynamoManager.go b/pkg/repository/aws/dynamoManager.go new file mode 100644 index 0000000..af14746 --- /dev/null +++ b/pkg/repository/aws/dynamoManager.go @@ -0,0 +1,27 @@ +package aws + +import ( + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/aws/aws-sdk-go/session" + "github.com/pkg/errors" +) + +type DynamoManager struct { + // need to look this up + Client *dynamodb.DDB +} + +func NewDynamoManager(session *session.Session) *DynamoManager { + return &DynamoManager{Client: dynamodb.New(session)} +} + +func (d *DynamoManager) GetItem(pk string) (string, error) { + // need to look this up + param, err := d.Client.GetItem(&dynamodb) + if err != nil { + return "", errors.WithStack(err) + } + + // need to look this up + return *param.Response, nil +} From 936fb1e346d0b0cd9b5a08f46f20b6a65b89ba6a Mon Sep 17 00:00:00 2001 From: Ruben Horn Date: Sun, 20 Feb 2022 12:56:21 +0100 Subject: [PATCH 03/67] badges on crowdactions and profiles --- docs/api2.yaml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/api2.yaml b/docs/api2.yaml index 1a8bbad..9a1f32a 100644 --- a/docs/api2.yaml +++ b/docs/api2.yaml @@ -417,7 +417,14 @@ paths: type: string default: success data: - $ref: '#/components/schemas/Profile' + allOf: + - $ref: '#/components/schemas/Profile' + - type: object + properties: + badges: + type: array + items: + $ref: '#/components/schemas/Badge' '403': $ref: '#/components/responses/UnsupportedClientVersion' '404': @@ -570,6 +577,10 @@ components: type: array items: $ref: '#/components/schemas/CommitmentOption' + badges: + type: array + items: + $ref: '#/components/schemas/Badge' participation: $ref: '#/components/schemas/Date' images: @@ -711,6 +722,23 @@ components: example: >- Hi, I am Max and I am trying to eat less meat to stop animal suffering. + Badge: + type: object + properties: + crowdactionID: + type: string + example: 'sustainability#food#88615462-2789-4159-8659-2ecfd33ef305' + title: + type: string + description: Title of the crowdactions + badge_title: + type: string + example: 'vegan hero' + badge_description: + type: string + example: 'The highest sacrifices deserve the highest awards' + badge_image: + $ref: '#/components/schemas/Image' Email: type: object properties: From 7ae52c79876f7a5062517afe6915912e102f9eb0 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Fri, 25 Feb 2022 14:52:40 +0100 Subject: [PATCH 04/67] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20launching=20own=20sa?= =?UTF-8?q?m=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samconfig.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 samconfig.yaml diff --git a/samconfig.yaml b/samconfig.yaml new file mode 100644 index 0000000..14cadb8 --- /dev/null +++ b/samconfig.yaml @@ -0,0 +1,12 @@ +version = 0.1 +[default] +[default.deploy] +[default.deploy.parameters] +s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1xoanv4heoh1g" +s3_prefix = "collaction-dev-edreinoso" +stack_name = "collaction-dev-edreinoso" +region = "eu-central-1" +confirm_changeset = true +capabilities = "CAPABILITY_IAM" +image_repositories = [] +parameter_overrides = "Stage=\"dev\" FirebaseProjectId=\"collaction-52ca9\" DomainParameter=\"\" SubdomainSuffixParameter=\"\" HostedZoneIdParameter=\"\" AcmCertificateArnParameter=\"\"" From 9963992dbb8508d488c53e776e6f9b011a9ea8e1 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 26 Feb 2022 08:58:52 +0100 Subject: [PATCH 05/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20deployed?= =?UTF-8?q?=20first=20function=20on=20to=20aws?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- pkg/handler/aws/crowdaction/main.go | 34 +++------ template.yaml | 105 +++++++++++++--------------- 3 files changed, 60 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index 7c5b4ba..2ad12b0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ _ignored/ .vscode/launch.json .vscode/extensions.json *.code-workspace - +*.gitconfig # VisualStudioCode Patch # Ignore all local history of files .history diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 556aa79..6b14fca 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -4,41 +4,25 @@ import ( "context" "encoding/json" "fmt" - "net/http" - "os" - "github.com/CollActionteam/collaction_backend/internal/models" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" - "github.com/go-playground/validator/v10" ) -var ( - tableName = os.Getenv("TABLE_NAME") -) - -func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { - fmt.Println("Entering the crowdaction endpoint") - - // invoking crowdaction model - var request models.CrowdActionRequest +func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) string { + fmt.Println("Hello Go, first message from AWS!") - // creating a new validator object - validate := validator.New() - - // validating against error - if err := validate.StructCtx(ctx, request); err != nil { - return errToResponse(err, http.StatusBadRequest), nil - } + crowdactionID := req.PathParameters["crowdactionID"] - // AWS session - //sess := session.Must(session.NewSession()) + fmt.Println("Getting the crowdactionID from the request") - if err := json.Unmarshal([]byte(req.Body), &request); err != nil { - return errToResponse(err, http.StatusBadRequest), nil + if crowdactionID == "" { + firstReturnValue := "Returning all crowdactions" + return firstReturnValue } + firstReturnValue := "Returning specific crowdaction" - return events.APIGatewayV2HTTPResponse{StatusCode: 200, Body: "Success!"}, nil + return firstReturnValue } func main() { diff --git a/template.yaml b/template.yaml index b2eff57..9588cec 100644 --- a/template.yaml +++ b/template.yaml @@ -1,9 +1,8 @@ -AWSTemplateFormatVersion: '2010-09-09' +AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > CollAction backend # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst - Globals: Function: Timeout: 10 @@ -35,13 +34,12 @@ Parameters: Type: String NoEcho: true Description: "ARN of certificate for CloudFront in region us-east-1 (Only for custom domain)" - + Conditions: shouldUseCustomDomainNames: !Not [!Equals [!Ref DomainParameter, ""]] Resources: - - DnsRecords: + DnsRecords: Type: AWS::Route53::RecordSetGroup Condition: shouldUseCustomDomainNames Properties: @@ -82,14 +80,14 @@ Resources: StaticContentDistribution: Type: AWS::CloudFront::Distribution Condition: shouldUseCustomDomainNames - Properties: + Properties: DistributionConfig: DefaultCacheBehavior: AllowedMethods: [HEAD, DELETE, POST, GET, OPTIONS, PUT, PATCH] TargetOriginId: StaticBucketOrigin ViewerProtocolPolicy: redirect-to-https ForwardedValues: - QueryString: 'false' + QueryString: "false" Cookies: Forward: none Enabled: true @@ -99,7 +97,7 @@ Resources: - Id: StaticBucketOrigin DomainName: !Sub ${StaticHostingBucket}.s3.${ AWS::Region }.amazonaws.com S3OriginConfig: - OriginAccessIdentity: !Sub 'origin-access-identity/cloudfront/${CloudFrontOriginIdentity}' + OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginIdentity}" ViewerCertificate: AcmCertificateArn: !Ref AcmCertificateArnParameter MinimumProtocolVersion: TLSv1.1_2016 @@ -108,21 +106,21 @@ Resources: HttpApiDomainName: Type: AWS::ApiGatewayV2::DomainName Condition: shouldUseCustomDomainNames - Properties: + Properties: DomainName: !Sub "api${SubdomainSuffixParameter}.${DomainParameter}" - DomainNameConfigurations: + DomainNameConfigurations: - EndpointType: REGIONAL CertificateArn: !Ref Certificate HttpApiMapping: Type: AWS::ApiGatewayV2::ApiMapping Condition: shouldUseCustomDomainNames - Properties: + Properties: ApiMappingKey: "" DomainName: !Sub "api${SubdomainSuffixParameter}.${DomainParameter}" ApiId: !Ref HttpApi Stage: !Ref HttpApi.Stage - DependsOn: + DependsOn: - HttpApiDomainName - HttpApi @@ -143,7 +141,7 @@ Resources: CorsConfiguration: AllowMethods: [GET] AllowOrigins: [http://localhost:8080] - + EmailContactFunction: Type: AWS::Serverless::Function Properties: @@ -160,19 +158,19 @@ Resources: Auth: Authorizer: "NONE" Policies: - - Version: '2012-10-17' + - Version: "2012-10-17" Statement: - Effect: Allow Action: - - 'ses:SendEmail' - - 'ses:SendRawEmail' - - 'ssm:GetParameter' - Resource: '*' + - "ses:SendEmail" + - "ses:SendRawEmail" + - "ssm:GetParameter" + Resource: "*" ProfilePictureUploadBucket: - Type: 'AWS::S3::Bucket' + Type: "AWS::S3::Bucket" StaticHostingBucket: - Type: 'AWS::S3::Bucket' + Type: "AWS::S3::Bucket" Properties: AccessControl: Private WebsiteConfiguration: @@ -196,10 +194,10 @@ Resources: BUCKET: !Ref ProfilePictureUploadBucket Policies: - Statement: - - Effect: Allow - Action: - - s3:PutObject* - Resource: '*' + - Effect: Allow + Action: + - s3:PutObject* + Resource: "*" Events: ProfilePictureUpload: Type: HttpApi @@ -209,7 +207,7 @@ Resources: ApiId: !Ref HttpApi ProcessProfilePictureFunction: - Type: 'AWS::Serverless::Function' + Type: "AWS::Serverless::Function" Properties: CodeUri: process-profile-picture/ Handler: process-profile-picture @@ -219,17 +217,18 @@ Resources: # Beware of recursive execution! Double check referenced buckets! OUTPUT_BUCKET_NAME: !Ref StaticHostingBucket KEY_PREIFX: profile-pictures/ - CLOUDFRONT_DISTRIBUTION: !If [shouldUseCustomDomainNames, !Ref StaticContentDistribution, ""] + CLOUDFRONT_DISTRIBUTION: + !If [shouldUseCustomDomainNames, !Ref StaticContentDistribution, ""] Policies: - Statement: - - Effect: Allow - Action: - - s3:GetObject* - - s3:PutObject* - - s3:DeleteObject* - - rekognition:DetectModerationLabels - - cloudfront:CreateInvalidation - Resource: '*' + - Effect: Allow + Action: + - s3:GetObject* + - s3:PutObject* + - s3:DeleteObject* + - rekognition:DetectModerationLabels + - cloudfront:CreateInvalidation + Resource: "*" Events: S3Event: Type: S3 @@ -256,10 +255,10 @@ Resources: GlobalSecondaryIndexes: - IndexName: "invertedIndex" KeySchema: - - AttributeName: "sk" - KeyType: "HASH" - - AttributeName: "pk" - KeyType: "RANGE" + - AttributeName: "sk" + KeyType: "HASH" + - AttributeName: "pk" + KeyType: "RANGE" Projection: ProjectionType: "ALL" # Data duplication is less costly than additional per primary key lookups (?) ProvisionedThroughput: @@ -269,7 +268,7 @@ Resources: CrowdactionFunction: Type: AWS::Serverless::Function Properties: - CodeUri: crowdaction/ + CodeUri: pkg/handler/aws/crowdaction Handler: crowdaction Runtime: go1.x Events: @@ -294,8 +293,7 @@ Resources: TABLE_NAME: !Ref SingleTable Policies: - DynamoDBCrudPolicy: - TableName: - !Ref SingleTable + TableName: !Ref SingleTable ParticipationQueue: Type: AWS::SQS::Queue @@ -318,8 +316,7 @@ Resources: MaximumBatchingWindowInSeconds: 300 #5min Policies: - DynamoDBCrudPolicy: - TableName: - !Ref SingleTable + TableName: !Ref SingleTable ParticipationFunction: Type: AWS::Serverless::Function @@ -341,15 +338,14 @@ Resources: ApiId: !Ref HttpApi Policies: - DynamoDBCrudPolicy: - TableName: - !Ref SingleTable + TableName: !Ref SingleTable - Statement: - - Sid: ParticipationQueuePutRecordPolicy - Effect: Allow - Action: - - sqs:SendMessage - Resource: !GetAtt ParticipationQueue.Arn - + - Sid: ParticipationQueuePutRecordPolicy + Effect: Allow + Action: + - sqs:SendMessage + Resource: !GetAtt ParticipationQueue.Arn + ProfileCRUDFunction: Type: AWS::Serverless::Function Properties: @@ -368,8 +364,7 @@ Resources: PROFILE_TABLE: !Ref ProfileTable Policies: - DynamoDBCrudPolicy: - TableName: - !Ref ProfileTable + TableName: !Ref ProfileTable # TODO use table SingleTabel instead ProfileTable: @@ -392,5 +387,5 @@ Outputs: Description: "CloudFront distribution endpoint URL for static files" Value: !Sub "https://static${SubdomainSuffixParameter}.${DomainParameter}/" TableName: - Value: !Ref SingleTable - Description: Table name of the newly created DynamoDB table \ No newline at end of file + Value: !Ref SingleTable + Description: Table name of the newly created DynamoDB table From 605e5643a40637276b63edca1da8874e5099f501 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 26 Feb 2022 09:00:56 +0100 Subject: [PATCH 06/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20removing?= =?UTF-8?q?=20extra=20copy=20of=20dynamo=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/repository/aws/dynamoManager.go | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 pkg/repository/aws/dynamoManager.go diff --git a/pkg/repository/aws/dynamoManager.go b/pkg/repository/aws/dynamoManager.go deleted file mode 100644 index af14746..0000000 --- a/pkg/repository/aws/dynamoManager.go +++ /dev/null @@ -1,27 +0,0 @@ -package aws - -import ( - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/session" - "github.com/pkg/errors" -) - -type DynamoManager struct { - // need to look this up - Client *dynamodb.DDB -} - -func NewDynamoManager(session *session.Session) *DynamoManager { - return &DynamoManager{Client: dynamodb.New(session)} -} - -func (d *DynamoManager) GetItem(pk string) (string, error) { - // need to look this up - param, err := d.Client.GetItem(&dynamodb) - if err != nil { - return "", errors.WithStack(err) - } - - // need to look this up - return *param.Response, nil -} From 0423b321cec882d32d33fe45b27bd8d097eae7f7 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 26 Feb 2022 09:14:01 +0100 Subject: [PATCH 07/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20init=20mod?= =?UTF-8?q?el=20and=20validation=20on=20request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/models/commitment.go | 0 internal/models/crowdaction.go | 33 +++++++++++++++++++++++------ pkg/handler/aws/crowdaction/main.go | 4 ++++ 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 internal/models/commitment.go diff --git a/internal/models/commitment.go b/internal/models/commitment.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/models/crowdaction.go b/internal/models/crowdaction.go index 7cf360a..269b641 100644 --- a/internal/models/crowdaction.go +++ b/internal/models/crowdaction.go @@ -1,13 +1,32 @@ package models type CrowdActionRequest struct { - Title string - Description string - AppVersion string + Data CrowdActionData `json:"data" validate:"required"` } -type CrowdAction struct { - CrowdactionID string - Title string - Description string +type CrowdactionParticipant struct { + Name string `json:"name,omitempty"` + UserID string `json:"userID,omitempty"` +} + +type CrowdactionImages struct { + Card string `json:"card,omitempty"` + Banner string `json:"banner,omitempty"` +} + +type CrowdActionData struct { + CrowdactionID string `json:"crowdactionID"` + Title string `json:"title"` + Description string `json:"description"` + Category string `json:"category"` + Subcategory string `json:"subcategory"` + Location string `json:"location"` + DateStart string `json:"date_start"` + DateEnd string `json:"date_end"` + DateLimitJoin string `json:"date_limit_join"` + PasswordJoin string `json:"password_join"` + CommitmentOptions []CommitmentOption `json:"commitment_options"` + ParticipationCount int `json:"participant_count"` + TopParticipants []CrowdactionParticipant `json:"top_participants"` + Images CrowdactionImages `json:"images"` } diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 6b14fca..4ec3ffe 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -7,11 +7,15 @@ import ( "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" + // "github.com/CollActionteam/collaction_backend/internal/contact" + // "github.com/CollActionteam/collaction_backend/internal/models" ) func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) string { fmt.Println("Hello Go, first message from AWS!") + // var request models.CrowdActionRequest + crowdactionID := req.PathParameters["crowdactionID"] fmt.Println("Getting the crowdactionID from the request") From d7daae2de3690ae229ae576a17bde4d554594e5b Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Fri, 4 Mar 2022 18:10:27 +0100 Subject: [PATCH 08/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20changed=20?= =?UTF-8?q?the=20model=20function=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/models/crowdaction.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/models/crowdaction.go b/internal/models/crowdaction.go index 269b641..11e03d1 100644 --- a/internal/models/crowdaction.go +++ b/internal/models/crowdaction.go @@ -1,7 +1,7 @@ package models -type CrowdActionRequest struct { - Data CrowdActionData `json:"data" validate:"required"` +type CrowdactionRequest struct { + Data CrowdactionData `json:"data" validate:"required"` } type CrowdactionParticipant struct { @@ -14,7 +14,7 @@ type CrowdactionImages struct { Banner string `json:"banner,omitempty"` } -type CrowdActionData struct { +type CrowdactionData struct { CrowdactionID string `json:"crowdactionID"` Title string `json:"title"` Description string `json:"description"` @@ -25,8 +25,8 @@ type CrowdActionData struct { DateEnd string `json:"date_end"` DateLimitJoin string `json:"date_limit_join"` PasswordJoin string `json:"password_join"` - CommitmentOptions []CommitmentOption `json:"commitment_options"` ParticipationCount int `json:"participant_count"` TopParticipants []CrowdactionParticipant `json:"top_participants"` Images CrowdactionImages `json:"images"` + // CommitmentOptions []CommitmentOption `json:"commitment_options"` } From e684acfaeb3e0661cd1035fae552f9f65d8e5c4b Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 9 Mar 2022 19:01:36 +0100 Subject: [PATCH 09/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20working=20?= =?UTF-8?q?on=20internal=20and=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 44 +++++++++++++++++ pkg/handler/aws/crowdaction/main.go | 71 ++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 internal/crowdactions/crowdaction.go diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go new file mode 100644 index 0000000..6ed0172 --- /dev/null +++ b/internal/crowdactions/crowdaction.go @@ -0,0 +1,44 @@ +package crowdaction + +import ( + "context" + "fmt" + + "github.com/CollActionteam/collaction_backend/internal/constants" + "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/utils" +) + +const Separator = "### app version:" + +type DynamoRepository interface { + GetDBItem(tableName string, pk string, crowdactionId string) (*models.CrowdactionData, error) +} + +type Service interface { + GetCrowdaction(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) +} + +type crowdaction struct { + dynamodb DynamoRepository +} + +func NewCrowdactionService(dynamodb DynamoRepository) Service { + return &crowdaction{dynamodb: dynamodb} +} + +/** + GET Crowdaction by Id +**/ +func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) { + item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionId) + if err != nil { + return nil, err + } + if item == nil { + return nil, fmt.Errorf("Crowdaction not found") + } + // var crowdaction models.CrowdactionData + // err = dynamodbattribute.UnmarshalMap(foo, &crowdaction) + return item, err +} diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 4ec3ffe..bc547e0 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -4,29 +4,84 @@ import ( "context" "encoding/json" "fmt" + "net/http" + crowdaction "github.com/CollActionteam/collaction_backend/internal/crowdactions" + "github.com/CollActionteam/collaction_backend/internal/models" + hnd "github.com/CollActionteam/collaction_backend/pkg/handler" + awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" + "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" + // "github.com/CollActionteam/collaction_backend/internal/contact" // "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/go-playground/validator/v10" ) +// type CrowdactionHandler struct { +// // getting all the main functions from the internal +// crowadction crowdactions.Dynamo +// } + +// // return crowdactions by +// func getCrowdactions (status string) (events.APIGatewayProxyResponse, error) {} + +// // return single crowdaction by ID +// func getCrowdaction (crowdactionId string, dynamoRepository Dynamo) (events.APIGatewayProxyResponse, error) { +// crowdaction, err := models. + +// // should call the internal and receive a response +// } + +// func retrieveInfoFromRequest(req events.APIGatewayV2HTTPRequest) (*models.Crowdaction, error) { +// crowdactionID := req.PathParameters["crowdactionID"] +// usrInf, err := auth.ExtractUserInfo(req) +// if err != nil { +// return nil, err +// } +// crowdaction, _ := models.GetCrowdaction(crowdactionID, constants.TableName) +// if crowdaction == nil { +// return "", "", nil, errors.New("crowdaction not found") +// } +// return crowdaction, nil +// } + func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) string { + var request models.CrowdactionRequest + + if err := json.Unmarshal([]byte(req.Body), &request); err != nil { + return errToResponse(err, http.StatusBadRequest), nil + } + fmt.Println("Hello Go, first message from AWS!") - // var request models.CrowdActionRequest + validate := validator.New() + if err := validate.StructCtx(ctx, request); err != nil { + body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) + return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil + } crowdactionID := req.PathParameters["crowdactionID"] + dynamoRepository := awsRepository.NewDynamo() - fmt.Println("Getting the crowdactionID from the request") + if err := crowdaction.NewCrowdactionService(dynamoRepository).GetCrowdaction(crowdactionID) + // fmt.Println("Getting the crowdactionID from the request") - if crowdactionID == "" { - firstReturnValue := "Returning all crowdactions" - return firstReturnValue - } - firstReturnValue := "Returning specific crowdaction" + // if crowdactionID == "" { + // status := req.QueryStringParameters["status"] + // switch status { + // case "": + // status = "joinable" + // case "featured": + // status = "joinable" + // } + // return getCrowdactions(status) + // } - return firstReturnValue + // return getCrowdaction(crowdactionID) + + return event.APIGatewayProxyResponse{StatusCode: 200, Body: string(body)}, nill } func main() { From 32666f855ef4762a8e9224599f397fbd7d8bec1b Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 10 Mar 2022 18:08:48 +0100 Subject: [PATCH 10/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20simple=20v?= =?UTF-8?q?ersion=20of=20GET=20request=20by=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 12 +++-- pkg/handler/aws/crowdaction/main.go | 70 +++++++++------------------- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 6ed0172..e351c44 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -7,12 +7,14 @@ import ( "github.com/CollActionteam/collaction_backend/internal/constants" "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" ) const Separator = "### app version:" type DynamoRepository interface { - GetDBItem(tableName string, pk string, crowdactionId string) (*models.CrowdactionData, error) + GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) } type Service interface { @@ -38,7 +40,9 @@ func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionId string) if item == nil { return nil, fmt.Errorf("Crowdaction not found") } - // var crowdaction models.CrowdactionData - // err = dynamodbattribute.UnmarshalMap(foo, &crowdaction) - return item, err + fmt.Printf("GetCrowdaction calling internal") + var crowdaction models.CrowdactionData + err = dynamodbattribute.UnmarshalMap(item, &crowdaction) + return &crowdaction, err + // return item, err } diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index bc547e0..d7d2f8d 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -6,48 +6,17 @@ import ( "fmt" "net/http" - crowdaction "github.com/CollActionteam/collaction_backend/internal/crowdactions" + cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" "github.com/CollActionteam/collaction_backend/internal/models" hnd "github.com/CollActionteam/collaction_backend/pkg/handler" awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" - - // "github.com/CollActionteam/collaction_backend/internal/contact" - // "github.com/CollActionteam/collaction_backend/internal/models" "github.com/go-playground/validator/v10" ) -// type CrowdactionHandler struct { -// // getting all the main functions from the internal -// crowadction crowdactions.Dynamo -// } - -// // return crowdactions by -// func getCrowdactions (status string) (events.APIGatewayProxyResponse, error) {} - -// // return single crowdaction by ID -// func getCrowdaction (crowdactionId string, dynamoRepository Dynamo) (events.APIGatewayProxyResponse, error) { -// crowdaction, err := models. - -// // should call the internal and receive a response -// } - -// func retrieveInfoFromRequest(req events.APIGatewayV2HTTPRequest) (*models.Crowdaction, error) { -// crowdactionID := req.PathParameters["crowdactionID"] -// usrInf, err := auth.ExtractUserInfo(req) -// if err != nil { -// return nil, err -// } -// crowdaction, _ := models.GetCrowdaction(crowdactionID, constants.TableName) -// if crowdaction == nil { -// return "", "", nil, errors.New("crowdaction not found") -// } -// return crowdaction, nil -// } - -func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) string { +func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { var request models.CrowdactionRequest if err := json.Unmarshal([]byte(req.Body), &request); err != nil { @@ -63,25 +32,30 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) string { } crowdactionID := req.PathParameters["crowdactionID"] + dynamoRepository := awsRepository.NewDynamo() - if err := crowdaction.NewCrowdactionService(dynamoRepository).GetCrowdaction(crowdactionID) - // fmt.Println("Getting the crowdactionID from the request") - - // if crowdactionID == "" { - // status := req.QueryStringParameters["status"] - // switch status { - // case "": - // status = "joinable" - // case "featured": - // status = "joinable" - // } - // return getCrowdactions(status) + fmt.Println("Getting the crowdactionID from the request") + + getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID) + + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + if getCrowdaction == nil { + return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil + } + + // if getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID); err != nil { + // return errToResponse(err, http.StatusInternalServerError), nil // } - // return getCrowdaction(crowdactionID) - - return event.APIGatewayProxyResponse{StatusCode: 200, Body: string(body)}, nill + jsonPayload, _ := json.Marshal(getCrowdaction) + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil + } func main() { From c25eec92eb684838d71e3f979bf1ced9ee3ceffa Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Fri, 11 Mar 2022 10:42:07 +0100 Subject: [PATCH 11/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20testing=20?= =?UTF-8?q?GET=20request=20by=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 7 ++++--- internal/models/commitment.go | 0 pkg/handler/aws/crowdaction/main.go | 26 ++++++++++++++++---------- pkg/repository/aws/dynamo.go | 5 +++++ 4 files changed, 25 insertions(+), 13 deletions(-) delete mode 100644 internal/models/commitment.go diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index e351c44..eeab50e 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -26,21 +26,22 @@ type crowdaction struct { } func NewCrowdactionService(dynamodb DynamoRepository) Service { + // fmt.Println("NewCrowdactionService") return &crowdaction{dynamodb: dynamodb} } /** GET Crowdaction by Id **/ -func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) { - item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionId) +func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { + // fmt.Println("GetCrowdaction calling internal:", crowdactionID) + item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionID) if err != nil { return nil, err } if item == nil { return nil, fmt.Errorf("Crowdaction not found") } - fmt.Printf("GetCrowdaction calling internal") var crowdaction models.CrowdactionData err = dynamodbattribute.UnmarshalMap(item, &crowdaction) return &crowdaction, err diff --git a/internal/models/commitment.go b/internal/models/commitment.go deleted file mode 100644 index e69de29..0000000 diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index d7d2f8d..4f05ce3 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -16,14 +16,19 @@ import ( "github.com/go-playground/validator/v10" ) +// func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { + // func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { + crowdactionID := req.PathParameters["crowdactionID"] + + fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest - if err := json.Unmarshal([]byte(req.Body), &request); err != nil { - return errToResponse(err, http.StatusBadRequest), nil - } + // if err := json.Unmarshal([]byte(req.Body), &request); err != nil { + // return errToResponse(err, http.StatusBadRequest), nil + // } - fmt.Println("Hello Go, first message from AWS!") + fmt.Println("bad request") validate := validator.New() if err := validate.StructCtx(ctx, request); err != nil { @@ -31,31 +36,32 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil } - crowdactionID := req.PathParameters["crowdactionID"] + fmt.Println("Request has been validated!") dynamoRepository := awsRepository.NewDynamo() - fmt.Println("Getting the crowdactionID from the request") + // crowdactionService := cwd.NewCrowdactionService(dynamoRepository) + + // getCrowdaction, err := crowdactionService.GetCrowdaction(ctx, crowdactionID) getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID) if err != nil { + // fmt.Println("There was an error") return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil } if getCrowdaction == nil { + // fmt.Println("No crowdaction available") return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil } - // if getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID); err != nil { - // return errToResponse(err, http.StatusInternalServerError), nil - // } + fmt.Println("getCrowdaction", getCrowdaction) jsonPayload, _ := json.Marshal(getCrowdaction) return events.APIGatewayV2HTTPResponse{ Body: string(jsonPayload), StatusCode: http.StatusOK, }, nil - } func main() { diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index d915d43..4969c7d 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -45,6 +45,7 @@ type UpdateItemData struct { } func NewDynamo() *Dynamo { + fmt.Println("New Dynamo Session") sess := session.Must(session.NewSession()) return &Dynamo{dbClient: dynamodb.New(sess)} } @@ -71,6 +72,8 @@ func (s *Dynamo) GetPrimaryKey(pk string, sk string) PrimaryKey { } func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]*dynamodb.AttributeValue, error) { + // fmt.Println("Calling GetDBItem", tableName, pk, sk) + result, err := s.dbClient.GetItem(&dynamodb.GetItemInput{ TableName: &tableName, Key: s.GetPrimaryKey(pk, sk), @@ -87,6 +90,8 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* if result == nil { return nil, nil } + + // fmt.Println("result from query: ", result) return result.Item, nil } From bae64a5a7a67313659cb72852a2850e1022afb4f Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Fri, 11 Mar 2022 10:58:26 +0100 Subject: [PATCH 12/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20creating?= =?UTF-8?q?=20external=20function=20to=20GET=20crowdaction=20by=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 1 - pkg/handler/aws/crowdaction/main.go | 65 ++++++++++++++++------------ 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index eeab50e..67228a4 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -45,5 +45,4 @@ func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionID string) var crowdaction models.CrowdactionData err = dynamodbattribute.UnmarshalMap(item, &crowdaction) return &crowdaction, err - // return item, err } diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 4f05ce3..366624c 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -16,6 +16,31 @@ import ( "github.com/go-playground/validator/v10" ) +func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { + dynamoRepository := awsRepository.NewDynamo() + getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID) + + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + if getCrowdaction == nil { + return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil + } + + fmt.Println("getCrowdaction", getCrowdaction) + + jsonPayload, _ := json.Marshal(getCrowdaction) + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil + + // return events.APIGatewayProxyResponse{ + // Body: string(body), + // StatusCode: http.StatusOK, + // }, nil +} + // func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { // func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { @@ -24,44 +49,30 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest + // This statement gives an error // if err := json.Unmarshal([]byte(req.Body), &request); err != nil { // return errToResponse(err, http.StatusBadRequest), nil // } - fmt.Println("bad request") - + // Do we really need validation for this type of requests? validate := validator.New() if err := validate.StructCtx(ctx, request); err != nil { body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil } - fmt.Println("Request has been validated!") - - dynamoRepository := awsRepository.NewDynamo() - - // crowdactionService := cwd.NewCrowdactionService(dynamoRepository) - - // getCrowdaction, err := crowdactionService.GetCrowdaction(ctx, crowdactionID) - - getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID) - - if err != nil { - // fmt.Println("There was an error") - return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } - if getCrowdaction == nil { - // fmt.Println("No crowdaction available") - return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil + if crowdactionID == "" { + status := req.QueryStringParameters["status"] + switch status { + case "": + status = "joinable" + case "featured": + status = "joinable" + } + // get all crowdactions } - - fmt.Println("getCrowdaction", getCrowdaction) - - jsonPayload, _ := json.Marshal(getCrowdaction) - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil + // get crowdaction by ID + return getCrowdactionByID(ctx, crowdactionID) } func main() { From 3d5c1a5d416076d4dff9bcfe8a4eb02e55fef118 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 19 Mar 2022 12:22:03 +0100 Subject: [PATCH 13/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20including?= =?UTF-8?q?=20query=20function=20in=20ddb=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/repository/aws/dynamo.go | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index 4969c7d..87c424c 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -4,11 +4,14 @@ import ( "fmt" "github.com/CollActionteam/collaction_backend/internal/constants" + "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) const ( @@ -95,6 +98,59 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* return result.Item, nil } +func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, *utils.PrimaryKey, error) { + // var crowdactions models.CrowdactionData + crowdactions := []models.CrowdactionData{} + keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) + expr, err := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() + + if err != nil { + return crowdactions, nil, err + } + + var exclusiveStartKey utils.PrimaryKey + + if startFrom != nil { + exclusiveStartKey = *startFrom + } + + result, err := s.dbClient.Query(&dynamodb.QueryInput{ + Limit: aws.Int64(utils.CrowdactionsPageLength), + ExclusiveStartKey: exclusiveStartKey, + TableName: aws.String(tableName), + ExpressionAttributeNames: expr.Names(), + ExpressionAttributeValues: expr.Values(), + KeyConditionExpression: expr.KeyCondition(), + FilterExpression: expr.Filter(), + }) + + // err = dynamodbattribute.UnmarshalMap(result, &crowdactions) + + for _, item := range result.Items { + var crowdaction models.CrowdactionData + err := dynamodbattribute.UnmarshalMap(item, &crowdaction) + + if err == nil { // have to figure out this error + crowdactions = append(crowdactions, crowdaction) + } + } + + if len(result.Items) != len(crowdactions) { + err = fmt.Errorf("Error unmarshelling %d items", len(result.Items)-len(crowdactions)) + } + + startFrom = nil + + if result.LastEvaluatedKey != nil && len(result.LastEvaluatedKey) > 0 { + lastPK := result.LastEvaluatedKey[utils.PartitionKey].S + lastSK := result.LastEvaluatedKey[utils.SortKey].S + exclusiveStartKey = utils.GetPrimaryKey(*lastPK, *lastSK) + startFrom = &exclusiveStartKey + } + + return crowdactions, startFrom, err +} + func (s *Dynamo) PutDBItem(tableName string, pk string, sk string, record interface{}) error { av, err := dynamodbattribute.MarshalMap(record) if err != nil { From 33a7ab1c5d30c5792aaa5d57abccabaa3d42d55a Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 19 Mar 2022 13:01:21 +0100 Subject: [PATCH 14/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20initial=20?= =?UTF-8?q?code=20base=20for=20GET=20crowdactions=20by=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 36 +++++++++++++++- pkg/handler/aws/crowdaction/main.go | 64 ++++++++++++++++++++++------ pkg/repository/aws/dynamo.go | 6 +-- 3 files changed, 90 insertions(+), 16 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 67228a4..11fdc56 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -9,22 +9,30 @@ import ( "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) const Separator = "### app version:" type DynamoRepository interface { GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) + Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } type Service interface { GetCrowdaction(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) + GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } - type crowdaction struct { dynamodb DynamoRepository } +const ( + KeyDateStart = "date_start" + KeyDateEnd = "date_end" + KeyDateJoinBefore = "date_limit_join" +) + func NewCrowdactionService(dynamodb DynamoRepository) Service { // fmt.Println("NewCrowdactionService") return &crowdaction{dynamodb: dynamodb} @@ -46,3 +54,29 @@ func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionID string) err = dynamodbattribute.UnmarshalMap(item, &crowdaction) return &crowdaction, err } + +/** + GET Crowdaction by Status +**/ +func (e *crowdaction) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { + crowdactions := []models.CrowdactionData{} // empty crowdaction array + + switch status { + case "joinable": + // call joinable crowdaction list + // crowdactions, _, err = models.ListJoinableCrowdactions(tableName, nil) // TODO future + filterCond := expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) + items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + return items, err + case "active": + filterCond := expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) + items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + return items, err + case "ended": + filterCond := expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) + items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + return items, err + default: + return crowdactions, nil + } +} diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 366624c..c3e3d1f 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -34,21 +34,54 @@ func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGa Body: string(jsonPayload), StatusCode: http.StatusOK, }, nil +} - // return events.APIGatewayProxyResponse{ - // Body: string(body), - // StatusCode: http.StatusOK, - // }, nil +func getAllCrowdactions(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { + dynamoRepository := awsRepository.NewDynamo() + var startFrom *utils.PrimaryKey + getAllCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, startFrom) + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + + jsonPayload, _ := json.Marshal(getAllCrowdactions) + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil + + // var crowdactions []models.Crowdaction + // var err error + + // /* TODO Send password for handling in app for MVP + // for i; i < len(crowdactions); i++) { + // if crowdactions[i].PasswordJoin != "" { + // crowdactions[i].PasswordJoin = passwordRequired + // } + // } + // */ + // if err != nil { + // return utils.GetMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + // } else { + // body, err := json.Marshal(crowdactions) + // if err != nil { + // return utils.GetMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + // } + // return events.APIGatewayProxyResponse{ + // Body: string(body), + // StatusCode: http.StatusOK, + // }, nil + // } } -// func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { - // func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) { crowdactionID := req.PathParameters["crowdactionID"] fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest + //dynamoRepository := awsRepository.NewDynamo() // should pass this dynamo variable + // This statement gives an error // if err := json.Unmarshal([]byte(req.Body), &request); err != nil { // return errToResponse(err, http.StatusBadRequest), nil @@ -63,14 +96,21 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP if crowdactionID == "" { status := req.QueryStringParameters["status"] - switch status { - case "": - status = "joinable" - case "featured": - status = "joinable" - } // get all crowdactions + return getAllCrowdactions(ctx, status) } + + // This switch statement is useless + // if crowdactionID == "" { + // status := req.QueryStringParameters["status"] + // switch status { + // case "": + // status = "joinable" + // case "featured": + // status = "joinable" + // } + // // get all crowdactions + // } // get crowdaction by ID return getCrowdactionByID(ctx, crowdactionID) } diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index 87c424c..f4b4d42 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -98,14 +98,14 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* return result.Item, nil } -func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, *utils.PrimaryKey, error) { +func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { // var crowdactions models.CrowdactionData crowdactions := []models.CrowdactionData{} keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) expr, err := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() if err != nil { - return crowdactions, nil, err + return crowdactions, err } var exclusiveStartKey utils.PrimaryKey @@ -148,7 +148,7 @@ func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom = &exclusiveStartKey } - return crowdactions, startFrom, err + return crowdactions, err } func (s *Dynamo) PutDBItem(tableName string, pk string, sk string, record interface{}) error { From b555b09c94b810b1a35d5ebe71ebeced4cc89033 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 19 Mar 2022 16:04:34 +0100 Subject: [PATCH 15/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20cleaning?= =?UTF-8?q?=20up,=20commitment=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 5 +-- internal/models/commitment.go | 8 ++++ internal/models/crowdaction.go | 2 +- pkg/handler/aws/crowdaction/main.go | 62 +++++++--------------------- pkg/repository/aws/dynamo.go | 5 +-- 5 files changed, 27 insertions(+), 55 deletions(-) create mode 100644 internal/models/commitment.go diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 11fdc56..74338b7 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -20,7 +20,7 @@ type DynamoRepository interface { } type Service interface { - GetCrowdaction(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) + GetCrowdactionById(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } type crowdaction struct { @@ -34,14 +34,13 @@ const ( ) func NewCrowdactionService(dynamodb DynamoRepository) Service { - // fmt.Println("NewCrowdactionService") return &crowdaction{dynamodb: dynamodb} } /** GET Crowdaction by Id **/ -func (e *crowdaction) GetCrowdaction(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { +func (e *crowdaction) GetCrowdactionById(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { // fmt.Println("GetCrowdaction calling internal:", crowdactionID) item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionID) if err != nil { diff --git a/internal/models/commitment.go b/internal/models/commitment.go new file mode 100644 index 0000000..e8dac0c --- /dev/null +++ b/internal/models/commitment.go @@ -0,0 +1,8 @@ +package models + +type CommitmentOption struct { + Id string `json:"id"` + Label string `json:"label"` + Description string `json:"description"` + Requires []CommitmentOption `json:"requires,omitempty"` +} diff --git a/internal/models/crowdaction.go b/internal/models/crowdaction.go index 11e03d1..67ec0c9 100644 --- a/internal/models/crowdaction.go +++ b/internal/models/crowdaction.go @@ -28,5 +28,5 @@ type CrowdactionData struct { ParticipationCount int `json:"participant_count"` TopParticipants []CrowdactionParticipant `json:"top_participants"` Images CrowdactionImages `json:"images"` - // CommitmentOptions []CommitmentOption `json:"commitment_options"` + CommitmentOptions []CommitmentOption `json:"commitment_options"` } diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index c3e3d1f..55744cc 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -18,7 +18,7 @@ import ( func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { dynamoRepository := awsRepository.NewDynamo() - getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdaction(ctx, crowdactionID) + getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) if err != nil { return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil @@ -27,8 +27,6 @@ func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGa return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil } - fmt.Println("getCrowdaction", getCrowdaction) - jsonPayload, _ := json.Marshal(getCrowdaction) return events.APIGatewayV2HTTPResponse{ Body: string(jsonPayload), @@ -36,42 +34,25 @@ func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGa }, nil } -func getAllCrowdactions(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { +func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { dynamoRepository := awsRepository.NewDynamo() var startFrom *utils.PrimaryKey - getAllCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, startFrom) + getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, startFrom) + if err != nil { return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } - - jsonPayload, _ := json.Marshal(getAllCrowdactions) - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil + } else { + jsonPayload, err := json.Marshal(getCrowdactions) - // var crowdactions []models.Crowdaction - // var err error + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } - // /* TODO Send password for handling in app for MVP - // for i; i < len(crowdactions); i++) { - // if crowdactions[i].PasswordJoin != "" { - // crowdactions[i].PasswordJoin = passwordRequired - // } - // } - // */ - // if err != nil { - // return utils.GetMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - // } else { - // body, err := json.Marshal(crowdactions) - // if err != nil { - // return utils.GetMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - // } - // return events.APIGatewayProxyResponse{ - // Body: string(body), - // StatusCode: http.StatusOK, - // }, nil - // } + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil + } } func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { @@ -96,22 +77,9 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP if crowdactionID == "" { status := req.QueryStringParameters["status"] - // get all crowdactions - return getAllCrowdactions(ctx, status) + return getCrowdactionsByStatus(ctx, status) } - // This switch statement is useless - // if crowdactionID == "" { - // status := req.QueryStringParameters["status"] - // switch status { - // case "": - // status = "joinable" - // case "featured": - // status = "joinable" - // } - // // get all crowdactions - // } - // get crowdaction by ID return getCrowdactionByID(ctx, crowdactionID) } diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index f4b4d42..3c60f7f 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -48,7 +48,6 @@ type UpdateItemData struct { } func NewDynamo() *Dynamo { - fmt.Println("New Dynamo Session") sess := session.Must(session.NewSession()) return &Dynamo{dbClient: dynamodb.New(sess)} } @@ -124,13 +123,11 @@ func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, FilterExpression: expr.Filter(), }) - // err = dynamodbattribute.UnmarshalMap(result, &crowdactions) - for _, item := range result.Items { var crowdaction models.CrowdactionData err := dynamodbattribute.UnmarshalMap(item, &crowdaction) - if err == nil { // have to figure out this error + if err == nil { crowdactions = append(crowdactions, crowdaction) } } From 841b968556714b995e49e4169ef23e127f3fba05 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sun, 20 Mar 2022 17:33:48 +0100 Subject: [PATCH 16/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20including?= =?UTF-8?q?=20the=20mock=20repository=20for=20dynamo=20and=20crowdaction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/mocks/repository/dynamoManager.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 pkg/mocks/repository/dynamoManager.go diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go new file mode 100644 index 0000000..cc119f4 --- /dev/null +++ b/pkg/mocks/repository/dynamoManager.go @@ -0,0 +1,17 @@ +package repository + +import ( + "context" + + "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/stretchr/testify/mock" +) + +type Dynamo struct { + mock.Mock +} + +func (d *Dynamo) GetCrowdactionById(ctx context.Context, data models.CrowdactionData) error { + args := d.Called(ctx, data) + return args.Error(0) +} From 483e006be11fd0a7580979fa91b88830f98081eb Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sun, 20 Mar 2022 17:56:16 +0100 Subject: [PATCH 17/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20modifying?= =?UTF-8?q?=20the=20mock=20repository=20to=20include=20GetCrowdactionBySta?= =?UTF-8?q?tus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/mocks/repository/dynamoManager.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index cc119f4..d79f053 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -3,7 +3,8 @@ package repository import ( "context" - "github.com/CollActionteam/collaction_backend/internal/models" + models "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" ) @@ -11,7 +12,12 @@ type Dynamo struct { mock.Mock } -func (d *Dynamo) GetCrowdactionById(ctx context.Context, data models.CrowdactionData) error { - args := d.Called(ctx, data) +func (d *Dynamo) GetCrowdactionById(ctx context.Context, crowdactionID string) error { + args := d.Called(ctx, crowdactionID) return args.Error(0) } + +func (d *Dynamo) GetCrowdactionByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { + args := d.Called(ctx, status, startFrom) + return args.Get(0).([]models.CrowdactionData), args.Error(1) +} From 9ce295a4ead3adeaf5750ab7ad10abd491d228a2 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sun, 20 Mar 2022 17:59:47 +0100 Subject: [PATCH 18/67] =?UTF-8?q?=F0=9F=9A=A7=20[crowdaction]=20removed=20?= =?UTF-8?q?unnecessary=20comments,=20per=20the=20feedback=20on=20pull=20re?= =?UTF-8?q?quest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/crowdactions/crowdaction.go | 9 ++------- pkg/handler/aws/crowdaction/README.md | 0 pkg/handler/aws/crowdaction/main.go | 9 +-------- pkg/repository/aws/dynamo.go | 2 +- 4 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 pkg/handler/aws/crowdaction/README.md diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 74338b7..03b765e 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -12,13 +12,10 @@ import ( "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) -const Separator = "### app version:" - type DynamoRepository interface { GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } - type Service interface { GetCrowdactionById(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) @@ -41,13 +38,13 @@ func NewCrowdactionService(dynamodb DynamoRepository) Service { GET Crowdaction by Id **/ func (e *crowdaction) GetCrowdactionById(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { - // fmt.Println("GetCrowdaction calling internal:", crowdactionID) + fmt.Println("GetCrowdaction calling internal:", crowdactionID) item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionID) if err != nil { return nil, err } if item == nil { - return nil, fmt.Errorf("Crowdaction not found") + return nil, fmt.Errorf("crowdaction not found") } var crowdaction models.CrowdactionData err = dynamodbattribute.UnmarshalMap(item, &crowdaction) @@ -62,8 +59,6 @@ func (e *crowdaction) GetCrowdactionsByStatus(ctx context.Context, status string switch status { case "joinable": - // call joinable crowdaction list - // crowdactions, _, err = models.ListJoinableCrowdactions(tableName, nil) // TODO future filterCond := expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) return items, err diff --git a/pkg/handler/aws/crowdaction/README.md b/pkg/handler/aws/crowdaction/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index 55744cc..d00b74d 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -17,6 +17,7 @@ import ( ) func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { + fmt.Println("getCrowdactionByID handler: crowdactionID ", crowdactionID) dynamoRepository := awsRepository.NewDynamo() getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) @@ -61,14 +62,6 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest - //dynamoRepository := awsRepository.NewDynamo() // should pass this dynamo variable - - // This statement gives an error - // if err := json.Unmarshal([]byte(req.Body), &request); err != nil { - // return errToResponse(err, http.StatusBadRequest), nil - // } - - // Do we really need validation for this type of requests? validate := validator.New() if err := validate.StructCtx(ctx, request); err != nil { body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index 3c60f7f..c83f451 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -74,7 +74,7 @@ func (s *Dynamo) GetPrimaryKey(pk string, sk string) PrimaryKey { } func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]*dynamodb.AttributeValue, error) { - // fmt.Println("Calling GetDBItem", tableName, pk, sk) + fmt.Println("Calling GetDBItem", tableName, pk, sk) result, err := s.dbClient.GetItem(&dynamodb.GetItemInput{ TableName: &tableName, From 8c5c28095c7aea596780fbd039d268aa3dfd893f Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 23 Mar 2022 17:24:19 +0100 Subject: [PATCH 19/67] [pull request] removing samconfig file from history --- samconfig.yaml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 samconfig.yaml diff --git a/samconfig.yaml b/samconfig.yaml deleted file mode 100644 index 14cadb8..0000000 --- a/samconfig.yaml +++ /dev/null @@ -1,12 +0,0 @@ -version = 0.1 -[default] -[default.deploy] -[default.deploy.parameters] -s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1xoanv4heoh1g" -s3_prefix = "collaction-dev-edreinoso" -stack_name = "collaction-dev-edreinoso" -region = "eu-central-1" -confirm_changeset = true -capabilities = "CAPABILITY_IAM" -image_repositories = [] -parameter_overrides = "Stage=\"dev\" FirebaseProjectId=\"collaction-52ca9\" DomainParameter=\"\" SubdomainSuffixParameter=\"\" HostedZoneIdParameter=\"\" AcmCertificateArnParameter=\"\"" From 99f52ef0a458f569847e5bcbda255d969cc28e11 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 23 Mar 2022 17:25:12 +0100 Subject: [PATCH 20/67] [pull request] ignoring samconfig file as per the pull request --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2ad12b0..9a84bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,6 @@ _ignored/ # MacOS .DS_Store -.idea \ No newline at end of file +.idea + +samconfig.yaml \ No newline at end of file From 4dc778923598e789caf3db1450a6b99342ede834 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 23 Mar 2022 17:36:47 +0100 Subject: [PATCH 21/67] [pull request] modified naming for the internal interface --- internal/crowdactions/crowdaction.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 03b765e..86d55dc 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -12,7 +12,7 @@ import ( "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) -type DynamoRepository interface { +type CrowdactionRepository interface { GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } @@ -21,7 +21,7 @@ type Service interface { GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } type crowdaction struct { - dynamodb DynamoRepository + dynamodb CrowdactionRepository } const ( @@ -30,7 +30,7 @@ const ( KeyDateJoinBefore = "date_limit_join" ) -func NewCrowdactionService(dynamodb DynamoRepository) Service { +func NewCrowdactionService(dynamodb CrowdactionRepository) Service { return &crowdaction{dynamodb: dynamodb} } From 18aa9636f17bc59c03d9aa86beb31b558b85841e Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 23 Mar 2022 17:50:17 +0100 Subject: [PATCH 22/67] [pull request] getting rid of useless else statement --- pkg/handler/aws/crowdaction/main.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index d00b74d..b23ed45 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "fmt" "net/http" cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" @@ -17,7 +16,6 @@ import ( ) func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { - fmt.Println("getCrowdactionByID handler: crowdactionID ", crowdactionID) dynamoRepository := awsRepository.NewDynamo() getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) @@ -42,24 +40,18 @@ func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGate if err != nil { return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } else { - jsonPayload, err := json.Marshal(getCrowdactions) + } + jsonPayload, _ := json.Marshal(getCrowdactions) - if err != nil { - return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil - } } func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { crowdactionID := req.PathParameters["crowdactionID"] - - fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest validate := validator.New() From 8fb01c0109178b58777bca0205ffa28760d07aa7 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 24 Mar 2022 12:19:26 +0100 Subject: [PATCH 23/67] [pull request] removing dynamodb dependencies in logic --- internal/crowdactions/crowdaction.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 86d55dc..6670347 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -7,14 +7,11 @@ import ( "github.com/CollActionteam/collaction_backend/internal/constants" "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" - "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) type CrowdactionRepository interface { - GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) - Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) + GetDBItem(tableName string, pk string, crowdactionId string) (*models.CrowdactionData, error) + Query(tableName string, filterCond string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) } type Service interface { GetCrowdactionById(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) @@ -46,9 +43,7 @@ func (e *crowdaction) GetCrowdactionById(ctx context.Context, crowdactionID stri if item == nil { return nil, fmt.Errorf("crowdaction not found") } - var crowdaction models.CrowdactionData - err = dynamodbattribute.UnmarshalMap(item, &crowdaction) - return &crowdaction, err + return item, err } /** @@ -59,16 +54,13 @@ func (e *crowdaction) GetCrowdactionsByStatus(ctx context.Context, status string switch status { case "joinable": - filterCond := expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + items, err := e.dynamodb.Query(constants.TableName, KeyDateJoinBefore, startFrom) return items, err case "active": - filterCond := expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + items, err := e.dynamodb.Query(constants.TableName, KeyDateStart, startFrom) return items, err case "ended": - filterCond := expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) + items, err := e.dynamodb.Query(constants.TableName, KeyDateEnd, startFrom) return items, err default: return crowdactions, nil From a47a23bae6fcc20179db19e115ac1423c59167d7 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 24 Mar 2022 22:45:21 +0100 Subject: [PATCH 24/67] [pull request] including mock repository and crowdaction test --- internal/crowdactions/crowdaction_test.go | 31 +++++++++++++++++++++++ pkg/mocks/repository/dynamoManager.go | 12 ++++----- 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 internal/crowdactions/crowdaction_test.go diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go new file mode 100644 index 0000000..5cf0076 --- /dev/null +++ b/internal/crowdactions/crowdaction_test.go @@ -0,0 +1,31 @@ +package crowdaction_test + +import ( + "context" + "fmt" + "testing" + + cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" + "github.com/CollActionteam/collaction_backend/pkg/mocks/repository" + "github.com/stretchr/testify/assert" +) + +func TestCrowdaction_GetCrowdactionById(t *testing.T, ctx context.Context) { + as := assert.New(t) + dynamoRepository := &repository.Dynamo{} + crowdactionID := "Helloworld2" + + t.Run("dev stage", func(t *testing.T) { + dynamoRepository.On("Send", context.Background(), crowdactionID).Return(nil).Once() + + service := cwd.NewCrowdactionService(dynamoRepository) + + crowdaction, err := service.GetCrowdactionById(ctx, crowdactionID) + + fmt.Printf("Hello world", crowdaction) + + as.NoError(err) + + dynamoRepository.AssertExpectations(t) + }) +} diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index d79f053..90eb984 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -1,8 +1,6 @@ package repository import ( - "context" - models "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" @@ -12,12 +10,12 @@ type Dynamo struct { mock.Mock } -func (d *Dynamo) GetCrowdactionById(ctx context.Context, crowdactionID string) error { - args := d.Called(ctx, crowdactionID) - return args.Error(0) +func (d *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.CrowdactionData, error) { + args := d.Called(tableName, pk, sk) + return args.Get(0).(*models.CrowdactionData), args.Error(1) } -func (d *Dynamo) GetCrowdactionByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - args := d.Called(ctx, status, startFrom) +func (d *Dynamo) Query(tableName string, filter string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { + args := d.Called(tableName, filter, startFrom) return args.Get(0).([]models.CrowdactionData), args.Error(1) } From 39c74174d32442563a70f23bd66a11539f565f99 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 24 Mar 2022 22:45:50 +0100 Subject: [PATCH 25/67] [pull request] cleaning up some unnecessary lines --- pkg/handler/aws/crowdaction/main.go | 1 - pkg/repository/aws/dynamo.go | 17 ++++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index b23ed45..afa316e 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -47,7 +47,6 @@ func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGate Body: string(jsonPayload), StatusCode: http.StatusOK, }, nil - } func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index c83f451..71f8831 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -73,9 +73,8 @@ func (s *Dynamo) GetPrimaryKey(pk string, sk string) PrimaryKey { } } -func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]*dynamodb.AttributeValue, error) { - fmt.Println("Calling GetDBItem", tableName, pk, sk) - +func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.CrowdactionData, error) { + var crowdaction models.CrowdactionData result, err := s.dbClient.GetItem(&dynamodb.GetItemInput{ TableName: &tableName, Key: s.GetPrimaryKey(pk, sk), @@ -84,7 +83,7 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* if err != nil { if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == dynamodb.ErrCodeResourceNotFoundException { - err = nil // Just return nil (not found is not an error) + err = nil } } return nil, err @@ -93,12 +92,12 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* return nil, nil } - // fmt.Println("result from query: ", result) - return result.Item, nil + err = dynamodbattribute.UnmarshalMap(result.Item, &crowdaction) + return &crowdaction, err } -func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - // var crowdactions models.CrowdactionData +func (s *Dynamo) Query(tableName string, filter string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { + filterCond := expression.Name(filter).GreaterThan(expression.Value(utils.GetDateStringNow())) crowdactions := []models.CrowdactionData{} keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) expr, err := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() @@ -133,7 +132,7 @@ func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, } if len(result.Items) != len(crowdactions) { - err = fmt.Errorf("Error unmarshelling %d items", len(result.Items)-len(crowdactions)) + err = fmt.Errorf("error unmarshelling %d items", len(result.Items)-len(crowdactions)) } startFrom = nil From 525b2b496f0f31f261e4fae4552dd2ef6a10e31e Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 16:20:06 +0200 Subject: [PATCH 26/67] [pull request] separating repository concerns --- internal/crowdactions/crowdaction.go | 56 +++++---------- pkg/repository/aws/crowdactionManager.go | 89 ++++++++++++++++++++++++ pkg/repository/aws/dynamo.go | 44 ++---------- 3 files changed, 113 insertions(+), 76 deletions(-) create mode 100644 pkg/repository/aws/crowdactionManager.go diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 6670347..804f650 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -4,21 +4,17 @@ import ( "context" "fmt" - "github.com/CollActionteam/collaction_backend/internal/constants" - "github.com/CollActionteam/collaction_backend/internal/models" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" ) -type CrowdactionRepository interface { - GetDBItem(tableName string, pk string, crowdactionId string) (*models.CrowdactionData, error) - Query(tableName string, filterCond string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) -} type Service interface { - GetCrowdactionById(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) - GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) + GetCrowdactionById(ctx context.Context, crowdactionId string) (*m.CrowdactionData, error) + GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) } -type crowdaction struct { - dynamodb CrowdactionRepository +type CrowdactionManager interface { + GetById(pk string, crowdactionId string) (*m.CrowdactionData, error) + GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) } const ( @@ -27,42 +23,26 @@ const ( KeyDateJoinBefore = "date_limit_join" ) -func NewCrowdactionService(dynamodb CrowdactionRepository) Service { - return &crowdaction{dynamodb: dynamodb} +type crowdactionService struct { + crowdactionRepository CrowdactionManager +} + +func NewCrowdactionService(crowdactionRepository CrowdactionManager) Service { + return &crowdactionService{crowdactionRepository: crowdactionRepository} } /** GET Crowdaction by Id **/ -func (e *crowdaction) GetCrowdactionById(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { - fmt.Println("GetCrowdaction calling internal:", crowdactionID) - item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionID) - if err != nil { - return nil, err - } - if item == nil { - return nil, fmt.Errorf("crowdaction not found") - } - return item, err +func (e *crowdactionService) GetCrowdactionById(ctx context.Context, crowdactionID string) (*m.CrowdactionData, error) { + fmt.Println("GetCrowdactionById", crowdactionID) + return e.crowdactionRepository.GetById(utils.PKCrowdaction, crowdactionID) } /** GET Crowdaction by Status **/ -func (e *crowdaction) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - crowdactions := []models.CrowdactionData{} // empty crowdaction array - - switch status { - case "joinable": - items, err := e.dynamodb.Query(constants.TableName, KeyDateJoinBefore, startFrom) - return items, err - case "active": - items, err := e.dynamodb.Query(constants.TableName, KeyDateStart, startFrom) - return items, err - case "ended": - items, err := e.dynamodb.Query(constants.TableName, KeyDateEnd, startFrom) - return items, err - default: - return crowdactions, nil - } +func (e *crowdactionService) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { + fmt.Println("GetCrowdactionsByStatus", status, startFrom) + return e.crowdactionRepository.GetByStatus(status, startFrom) } diff --git a/pkg/repository/aws/crowdactionManager.go b/pkg/repository/aws/crowdactionManager.go new file mode 100644 index 0000000..fb29b7b --- /dev/null +++ b/pkg/repository/aws/crowdactionManager.go @@ -0,0 +1,89 @@ +package aws + +import ( + "fmt" + + "github.com/CollActionteam/collaction_backend/internal/constants" + m "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/utils" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/aws/aws-sdk-go/service/dynamodb/expression" +) + +type Crowdaction interface { + GetById(pk string, sk string) (*m.CrowdactionData, error) + GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) +} + +const ( + KeyDateStart = "date_start" + KeyDateEnd = "date_end" + KeyDateJoinBefore = "date_limit_join" +) + +type crowdaction struct { + dbClient *Dynamo +} + +func NewCrowdaction(dynamo *Dynamo) Crowdaction { + return &crowdaction{dbClient: dynamo} +} + +/** + GET Crowdaction by Id +**/ +func (s *crowdaction) GetById(pk string, sk string) (*m.CrowdactionData, error) { + item, err := s.dbClient.GetDBItem(constants.TableName, pk, sk) + + if item == nil || err != nil { + return nil, err + } + + var c m.CrowdactionData + err = dynamodbattribute.UnmarshalMap(item, &c) + + return &c, err +} + +/** + GET Crowdaction by Status +**/ +func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { + crowdactions := []m.CrowdactionData{} + var filterCond expression.ConditionBuilder + + switch status { + case "joinable": + filterCond = expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: joinable", filterCond) + case "active": + filterCond = expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: active", filterCond) + case "ended": + filterCond = expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: ended", filterCond) + default: + fmt.Println("None of the edge cases matched") + } + + items, err := s.dbClient.Query(constants.TableName, filterCond, startFrom) + + if items == nil || err != nil { + return nil, err + } + + for _, foo := range items { + var crowdaction m.CrowdactionData + err := dynamodbattribute.UnmarshalMap(foo, &crowdaction) + + if err == nil { + crowdactions = append(crowdactions, crowdaction) + } + } + + if len(items) != len(crowdactions) { + err = fmt.Errorf("error unmarshelling %d items", len(items)-len(crowdactions)) + } + + return crowdactions, err +} diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index 71f8831..0698ba8 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/CollActionteam/collaction_backend/internal/constants" - "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -73,8 +72,7 @@ func (s *Dynamo) GetPrimaryKey(pk string, sk string) PrimaryKey { } } -func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.CrowdactionData, error) { - var crowdaction models.CrowdactionData +func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]*dynamodb.AttributeValue, error) { result, err := s.dbClient.GetItem(&dynamodb.GetItemInput{ TableName: &tableName, Key: s.GetPrimaryKey(pk, sk), @@ -83,7 +81,7 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.Crow if err != nil { if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == dynamodb.ErrCodeResourceNotFoundException { - err = nil + err = nil // Just return nil (not found is not an error) } } return nil, err @@ -91,20 +89,12 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.Crow if result == nil { return nil, nil } - - err = dynamodbattribute.UnmarshalMap(result.Item, &crowdaction) - return &crowdaction, err + return result.Item, nil } -func (s *Dynamo) Query(tableName string, filter string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - filterCond := expression.Name(filter).GreaterThan(expression.Value(utils.GetDateStringNow())) - crowdactions := []models.CrowdactionData{} +func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]map[string]*dynamodb.AttributeValue, error) { keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) - expr, err := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() - - if err != nil { - return crowdactions, err - } + expr, _ := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() var exclusiveStartKey utils.PrimaryKey @@ -122,29 +112,7 @@ func (s *Dynamo) Query(tableName string, filter string, startFrom *utils.Primary FilterExpression: expr.Filter(), }) - for _, item := range result.Items { - var crowdaction models.CrowdactionData - err := dynamodbattribute.UnmarshalMap(item, &crowdaction) - - if err == nil { - crowdactions = append(crowdactions, crowdaction) - } - } - - if len(result.Items) != len(crowdactions) { - err = fmt.Errorf("error unmarshelling %d items", len(result.Items)-len(crowdactions)) - } - - startFrom = nil - - if result.LastEvaluatedKey != nil && len(result.LastEvaluatedKey) > 0 { - lastPK := result.LastEvaluatedKey[utils.PartitionKey].S - lastSK := result.LastEvaluatedKey[utils.SortKey].S - exclusiveStartKey = utils.GetPrimaryKey(*lastPK, *lastSK) - startFrom = &exclusiveStartKey - } - - return crowdactions, err + return result.Items, err } func (s *Dynamo) PutDBItem(tableName string, pk string, sk string, record interface{}) error { From 595b73703ce4398c949c0332102b12a0396edd9a Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 16:21:00 +0200 Subject: [PATCH 27/67] [pull request] modifying test cases with new repository structure --- internal/crowdactions/crowdaction_test.go | 2 +- pkg/mocks/repository/dynamoManager.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index 5cf0076..379b66e 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -22,7 +22,7 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T, ctx context.Context) { crowdaction, err := service.GetCrowdactionById(ctx, crowdactionID) - fmt.Printf("Hello world", crowdaction) + fmt.Println("Hello world", crowdaction) as.NoError(err) diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index 90eb984..a868639 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -10,12 +10,12 @@ type Dynamo struct { mock.Mock } -func (d *Dynamo) GetDBItem(tableName string, pk string, sk string) (*models.CrowdactionData, error) { - args := d.Called(tableName, pk, sk) +func (d *Dynamo) GetById(pk string, sk string) (*models.CrowdactionData, error) { + args := d.Called(pk, sk) return args.Get(0).(*models.CrowdactionData), args.Error(1) } -func (d *Dynamo) Query(tableName string, filter string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - args := d.Called(tableName, filter, startFrom) +func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { + args := d.Called(filterCond, startFrom) return args.Get(0).([]models.CrowdactionData), args.Error(1) } From 98f45af7afdf84d1fc8036bda16805ea8aa42073 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 16:21:44 +0200 Subject: [PATCH 28/67] [pull request] changing dynamo repository call from crowdaction main handler --- pkg/handler/aws/crowdaction/main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index afa316e..dc32435 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -16,7 +16,7 @@ import ( ) func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { - dynamoRepository := awsRepository.NewDynamo() + dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) if err != nil { @@ -34,9 +34,8 @@ func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGa } func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { - dynamoRepository := awsRepository.NewDynamo() - var startFrom *utils.PrimaryKey - getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, startFrom) + dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) + getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, nil) if err != nil { return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil From 45cb5932ad8dae05aef9d41bde354ba05ab20172 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 16:27:49 +0200 Subject: [PATCH 29/67] [pull request] changing parameters to pass unit test case --- internal/crowdactions/crowdaction_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index 379b66e..342cd38 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -10,9 +10,10 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCrowdaction_GetCrowdactionById(t *testing.T, ctx context.Context) { +func TestCrowdaction_GetCrowdactionById(t *testing.T) { as := assert.New(t) dynamoRepository := &repository.Dynamo{} + var ctx context.Context crowdactionID := "Helloworld2" t.Run("dev stage", func(t *testing.T) { From 93138e25040e70c5c82fb01237e54b3cb5fcc8df Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 16:33:45 +0200 Subject: [PATCH 30/67] [pull request] changing crowdactionID from test case --- internal/crowdactions/crowdaction_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index 342cd38..df7b5ad 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -14,7 +14,7 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T) { as := assert.New(t) dynamoRepository := &repository.Dynamo{} var ctx context.Context - crowdactionID := "Helloworld2" + crowdactionID := "sustainability#food#185f66fd" t.Run("dev stage", func(t *testing.T) { dynamoRepository.On("Send", context.Background(), crowdactionID).Return(nil).Once() From f03c63a66d0b29b42c66d021948248a3aaa94b55 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 28 Mar 2022 17:34:00 +0200 Subject: [PATCH 31/67] [pull request] changing method call for crowdaction test --- internal/crowdactions/crowdaction_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index df7b5ad..8ff639a 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -17,7 +17,7 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T) { crowdactionID := "sustainability#food#185f66fd" t.Run("dev stage", func(t *testing.T) { - dynamoRepository.On("Send", context.Background(), crowdactionID).Return(nil).Once() + dynamoRepository.On("GetById", context.Background(), crowdactionID).Return(nil).Once() service := cwd.NewCrowdactionService(dynamoRepository) From 8449139843b29b7d4adee3c8a8ab688777e4fe0e Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 29 Mar 2022 10:43:21 +0200 Subject: [PATCH 32/67] [pull request] fixing parameter issue in crowdaction_test --- internal/crowdactions/crowdaction_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index 8ff639a..a22842e 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -7,6 +7,7 @@ import ( cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" "github.com/CollActionteam/collaction_backend/pkg/mocks/repository" + "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/assert" ) @@ -17,7 +18,7 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T) { crowdactionID := "sustainability#food#185f66fd" t.Run("dev stage", func(t *testing.T) { - dynamoRepository.On("GetById", context.Background(), crowdactionID).Return(nil).Once() + dynamoRepository.On("GetById", utils.PKCrowdaction, crowdactionID).Return(nil).Once() service := cwd.NewCrowdactionService(dynamoRepository) From 14f671af677054e6c0e7af1ac832eacc87765688 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 29 Mar 2022 10:52:56 +0200 Subject: [PATCH 33/67] [pull request] testing issue with the args.get(x) call in mock/dynamo repository --- pkg/mocks/repository/dynamoManager.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index a868639..3158b8b 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -1,6 +1,8 @@ package repository import ( + "fmt" + models "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" @@ -12,6 +14,10 @@ type Dynamo struct { func (d *Dynamo) GetById(pk string, sk string) (*models.CrowdactionData, error) { args := d.Called(pk, sk) + fmt.Println("Before the args") + fmt.Println("Args", args) + fmt.Println("Args", args.Get(0)) + fmt.Println("After the args") return args.Get(0).(*models.CrowdactionData), args.Error(1) } From 09ed55a7a05bd69fa5a57634a4c605fe2db05efe Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 29 Mar 2022 11:02:08 +0200 Subject: [PATCH 34/67] [pull request] including Mock in each of the function calls from the dynamo repository --- pkg/mocks/repository/dynamoManager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index 3158b8b..1a2d2f4 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -13,7 +13,7 @@ type Dynamo struct { } func (d *Dynamo) GetById(pk string, sk string) (*models.CrowdactionData, error) { - args := d.Called(pk, sk) + args := d.Mock.Called(pk, sk) fmt.Println("Before the args") fmt.Println("Args", args) fmt.Println("Args", args.Get(0)) @@ -22,6 +22,6 @@ func (d *Dynamo) GetById(pk string, sk string) (*models.CrowdactionData, error) } func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - args := d.Called(filterCond, startFrom) + args := d.Mock.Called(filterCond, startFrom) return args.Get(0).([]models.CrowdactionData), args.Error(1) } From 589a25ced77940129a0fb0a0125d673254e3f5fc Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 29 Mar 2022 11:44:12 +0200 Subject: [PATCH 35/67] [pull request] modifying test cases for crowdaction --- internal/crowdactions/crowdaction_test.go | 5 ++++- pkg/mocks/repository/dynamoManager.go | 16 +++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index a22842e..5ae810a 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -6,7 +6,9 @@ import ( "testing" cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/pkg/mocks/repository" + "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/assert" ) @@ -15,10 +17,11 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T) { as := assert.New(t) dynamoRepository := &repository.Dynamo{} var ctx context.Context + var crowdactions *m.CrowdactionData crowdactionID := "sustainability#food#185f66fd" t.Run("dev stage", func(t *testing.T) { - dynamoRepository.On("GetById", utils.PKCrowdaction, crowdactionID).Return(nil).Once() + dynamoRepository.On("GetById", utils.PKCrowdaction, crowdactionID).Return(crowdactions, nil).Once() service := cwd.NewCrowdactionService(dynamoRepository) diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index 1a2d2f4..3d37bab 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -1,9 +1,7 @@ package repository import ( - "fmt" - - models "github.com/CollActionteam/collaction_backend/internal/models" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" ) @@ -12,16 +10,12 @@ type Dynamo struct { mock.Mock } -func (d *Dynamo) GetById(pk string, sk string) (*models.CrowdactionData, error) { +func (d *Dynamo) GetById(pk string, sk string) (*m.CrowdactionData, error) { args := d.Mock.Called(pk, sk) - fmt.Println("Before the args") - fmt.Println("Args", args) - fmt.Println("Args", args.Get(0)) - fmt.Println("After the args") - return args.Get(0).(*models.CrowdactionData), args.Error(1) + return args.Get(0).(*m.CrowdactionData), args.Error(1) } -func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { +func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { args := d.Mock.Called(filterCond, startFrom) - return args.Get(0).([]models.CrowdactionData), args.Error(1) + return args.Get(0).([]m.CrowdactionData), args.Error(1) } From 72c469fcf8d54fce694d2ebafa396ef0cfede1d9 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 23 Mar 2022 17:24:19 +0100 Subject: [PATCH 36/67] [pull request] changes done based on feedback [pull request] ignoring samconfig file as per the pull request [pull request] modified naming for the internal interface [pull request] getting rid of useless else statement [pull request] removing dynamodb dependencies in logic [pull request] including mock repository and crowdaction test [pull request] cleaning up some unnecessary lines [pull request] separating repository concerns [pull request] modifying test cases with new repository structure [pull request] changing dynamo repository call from crowdaction main handler [pull request] changing parameters to pass unit test case [pull request] changing crowdactionID from test case [pull request] changing method call for crowdaction test [pull request] fixing parameter issue in crowdaction_test [pull request] testing issue with the args.get(x) call in mock/dynamo repository [pull request] including Mock in each of the function calls from the dynamo repository [pull request] modifying test cases for crowdaction --- .gitignore | 4 +- internal/crowdactions/crowdaction.go | 64 +++++----------- internal/crowdactions/crowdaction_test.go | 36 +++++++++ pkg/handler/aws/crowdaction/main.go | 28 +++---- pkg/mocks/repository/dynamoManager.go | 16 ++-- pkg/repository/aws/crowdactionManager.go | 89 +++++++++++++++++++++++ pkg/repository/aws/dynamo.go | 39 +--------- samconfig.yaml | 12 --- 8 files changed, 165 insertions(+), 123 deletions(-) create mode 100644 internal/crowdactions/crowdaction_test.go create mode 100644 pkg/repository/aws/crowdactionManager.go delete mode 100644 samconfig.yaml diff --git a/.gitignore b/.gitignore index 2ad12b0..9a84bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,6 @@ _ignored/ # MacOS .DS_Store -.idea \ No newline at end of file +.idea + +samconfig.yaml \ No newline at end of file diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 03b765e..804f650 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -4,24 +4,17 @@ import ( "context" "fmt" - "github.com/CollActionteam/collaction_backend/internal/constants" - "github.com/CollActionteam/collaction_backend/internal/models" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" - "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) -type DynamoRepository interface { - GetDBItem(tableName string, pk string, crowdactionId string) (map[string]*dynamodb.AttributeValue, error) - Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) -} type Service interface { - GetCrowdactionById(ctx context.Context, crowdactionId string) (*models.CrowdactionData, error) - GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) + GetCrowdactionById(ctx context.Context, crowdactionId string) (*m.CrowdactionData, error) + GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) } -type crowdaction struct { - dynamodb DynamoRepository +type CrowdactionManager interface { + GetById(pk string, crowdactionId string) (*m.CrowdactionData, error) + GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) } const ( @@ -30,47 +23,26 @@ const ( KeyDateJoinBefore = "date_limit_join" ) -func NewCrowdactionService(dynamodb DynamoRepository) Service { - return &crowdaction{dynamodb: dynamodb} +type crowdactionService struct { + crowdactionRepository CrowdactionManager +} + +func NewCrowdactionService(crowdactionRepository CrowdactionManager) Service { + return &crowdactionService{crowdactionRepository: crowdactionRepository} } /** GET Crowdaction by Id **/ -func (e *crowdaction) GetCrowdactionById(ctx context.Context, crowdactionID string) (*models.CrowdactionData, error) { - fmt.Println("GetCrowdaction calling internal:", crowdactionID) - item, err := e.dynamodb.GetDBItem(constants.TableName, utils.PKCrowdaction, crowdactionID) - if err != nil { - return nil, err - } - if item == nil { - return nil, fmt.Errorf("crowdaction not found") - } - var crowdaction models.CrowdactionData - err = dynamodbattribute.UnmarshalMap(item, &crowdaction) - return &crowdaction, err +func (e *crowdactionService) GetCrowdactionById(ctx context.Context, crowdactionID string) (*m.CrowdactionData, error) { + fmt.Println("GetCrowdactionById", crowdactionID) + return e.crowdactionRepository.GetById(utils.PKCrowdaction, crowdactionID) } /** GET Crowdaction by Status **/ -func (e *crowdaction) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - crowdactions := []models.CrowdactionData{} // empty crowdaction array - - switch status { - case "joinable": - filterCond := expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) - return items, err - case "active": - filterCond := expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) - return items, err - case "ended": - filterCond := expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) - items, err := e.dynamodb.Query(constants.TableName, filterCond, startFrom) - return items, err - default: - return crowdactions, nil - } +func (e *crowdactionService) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { + fmt.Println("GetCrowdactionsByStatus", status, startFrom) + return e.crowdactionRepository.GetByStatus(status, startFrom) } diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go new file mode 100644 index 0000000..5ae810a --- /dev/null +++ b/internal/crowdactions/crowdaction_test.go @@ -0,0 +1,36 @@ +package crowdaction_test + +import ( + "context" + "fmt" + "testing" + + cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" + m "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/pkg/mocks/repository" + + "github.com/CollActionteam/collaction_backend/utils" + "github.com/stretchr/testify/assert" +) + +func TestCrowdaction_GetCrowdactionById(t *testing.T) { + as := assert.New(t) + dynamoRepository := &repository.Dynamo{} + var ctx context.Context + var crowdactions *m.CrowdactionData + crowdactionID := "sustainability#food#185f66fd" + + t.Run("dev stage", func(t *testing.T) { + dynamoRepository.On("GetById", utils.PKCrowdaction, crowdactionID).Return(crowdactions, nil).Once() + + service := cwd.NewCrowdactionService(dynamoRepository) + + crowdaction, err := service.GetCrowdactionById(ctx, crowdactionID) + + fmt.Println("Hello world", crowdaction) + + as.NoError(err) + + dynamoRepository.AssertExpectations(t) + }) +} diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index d00b74d..dc32435 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "fmt" "net/http" cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" @@ -17,8 +16,7 @@ import ( ) func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { - fmt.Println("getCrowdactionByID handler: crowdactionID ", crowdactionID) - dynamoRepository := awsRepository.NewDynamo() + dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) if err != nil { @@ -36,30 +34,22 @@ func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGa } func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { - dynamoRepository := awsRepository.NewDynamo() - var startFrom *utils.PrimaryKey - getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, startFrom) + dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) + getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, nil) if err != nil { return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } else { - jsonPayload, err := json.Marshal(getCrowdactions) - - if err != nil { - return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } - - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil } + jsonPayload, _ := json.Marshal(getCrowdactions) + + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil } func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { crowdactionID := req.PathParameters["crowdactionID"] - - fmt.Println("Hello Go, first message from CollAction AWS: ", crowdactionID) var request models.CrowdactionRequest validate := validator.New() diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index d79f053..3d37bab 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -1,9 +1,7 @@ package repository import ( - "context" - - models "github.com/CollActionteam/collaction_backend/internal/models" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" ) @@ -12,12 +10,12 @@ type Dynamo struct { mock.Mock } -func (d *Dynamo) GetCrowdactionById(ctx context.Context, crowdactionID string) error { - args := d.Called(ctx, crowdactionID) - return args.Error(0) +func (d *Dynamo) GetById(pk string, sk string) (*m.CrowdactionData, error) { + args := d.Mock.Called(pk, sk) + return args.Get(0).(*m.CrowdactionData), args.Error(1) } -func (d *Dynamo) GetCrowdactionByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - args := d.Called(ctx, status, startFrom) - return args.Get(0).([]models.CrowdactionData), args.Error(1) +func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { + args := d.Mock.Called(filterCond, startFrom) + return args.Get(0).([]m.CrowdactionData), args.Error(1) } diff --git a/pkg/repository/aws/crowdactionManager.go b/pkg/repository/aws/crowdactionManager.go new file mode 100644 index 0000000..fb29b7b --- /dev/null +++ b/pkg/repository/aws/crowdactionManager.go @@ -0,0 +1,89 @@ +package aws + +import ( + "fmt" + + "github.com/CollActionteam/collaction_backend/internal/constants" + m "github.com/CollActionteam/collaction_backend/internal/models" + "github.com/CollActionteam/collaction_backend/utils" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/aws/aws-sdk-go/service/dynamodb/expression" +) + +type Crowdaction interface { + GetById(pk string, sk string) (*m.CrowdactionData, error) + GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) +} + +const ( + KeyDateStart = "date_start" + KeyDateEnd = "date_end" + KeyDateJoinBefore = "date_limit_join" +) + +type crowdaction struct { + dbClient *Dynamo +} + +func NewCrowdaction(dynamo *Dynamo) Crowdaction { + return &crowdaction{dbClient: dynamo} +} + +/** + GET Crowdaction by Id +**/ +func (s *crowdaction) GetById(pk string, sk string) (*m.CrowdactionData, error) { + item, err := s.dbClient.GetDBItem(constants.TableName, pk, sk) + + if item == nil || err != nil { + return nil, err + } + + var c m.CrowdactionData + err = dynamodbattribute.UnmarshalMap(item, &c) + + return &c, err +} + +/** + GET Crowdaction by Status +**/ +func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { + crowdactions := []m.CrowdactionData{} + var filterCond expression.ConditionBuilder + + switch status { + case "joinable": + filterCond = expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: joinable", filterCond) + case "active": + filterCond = expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: active", filterCond) + case "ended": + filterCond = expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) + fmt.Println("GetByStatus: ended", filterCond) + default: + fmt.Println("None of the edge cases matched") + } + + items, err := s.dbClient.Query(constants.TableName, filterCond, startFrom) + + if items == nil || err != nil { + return nil, err + } + + for _, foo := range items { + var crowdaction m.CrowdactionData + err := dynamodbattribute.UnmarshalMap(foo, &crowdaction) + + if err == nil { + crowdactions = append(crowdactions, crowdaction) + } + } + + if len(items) != len(crowdactions) { + err = fmt.Errorf("error unmarshelling %d items", len(items)-len(crowdactions)) + } + + return crowdactions, err +} diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index c83f451..0698ba8 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/CollActionteam/collaction_backend/internal/constants" - "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -74,8 +73,6 @@ func (s *Dynamo) GetPrimaryKey(pk string, sk string) PrimaryKey { } func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]*dynamodb.AttributeValue, error) { - fmt.Println("Calling GetDBItem", tableName, pk, sk) - result, err := s.dbClient.GetItem(&dynamodb.GetItemInput{ TableName: &tableName, Key: s.GetPrimaryKey(pk, sk), @@ -92,20 +89,12 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* if result == nil { return nil, nil } - - // fmt.Println("result from query: ", result) return result.Item, nil } -func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]models.CrowdactionData, error) { - // var crowdactions models.CrowdactionData - crowdactions := []models.CrowdactionData{} +func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]map[string]*dynamodb.AttributeValue, error) { keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) - expr, err := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() - - if err != nil { - return crowdactions, err - } + expr, _ := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() var exclusiveStartKey utils.PrimaryKey @@ -123,29 +112,7 @@ func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, FilterExpression: expr.Filter(), }) - for _, item := range result.Items { - var crowdaction models.CrowdactionData - err := dynamodbattribute.UnmarshalMap(item, &crowdaction) - - if err == nil { - crowdactions = append(crowdactions, crowdaction) - } - } - - if len(result.Items) != len(crowdactions) { - err = fmt.Errorf("Error unmarshelling %d items", len(result.Items)-len(crowdactions)) - } - - startFrom = nil - - if result.LastEvaluatedKey != nil && len(result.LastEvaluatedKey) > 0 { - lastPK := result.LastEvaluatedKey[utils.PartitionKey].S - lastSK := result.LastEvaluatedKey[utils.SortKey].S - exclusiveStartKey = utils.GetPrimaryKey(*lastPK, *lastSK) - startFrom = &exclusiveStartKey - } - - return crowdactions, err + return result.Items, err } func (s *Dynamo) PutDBItem(tableName string, pk string, sk string, record interface{}) error { diff --git a/samconfig.yaml b/samconfig.yaml deleted file mode 100644 index 14cadb8..0000000 --- a/samconfig.yaml +++ /dev/null @@ -1,12 +0,0 @@ -version = 0.1 -[default] -[default.deploy] -[default.deploy.parameters] -s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1xoanv4heoh1g" -s3_prefix = "collaction-dev-edreinoso" -stack_name = "collaction-dev-edreinoso" -region = "eu-central-1" -confirm_changeset = true -capabilities = "CAPABILITY_IAM" -image_repositories = [] -parameter_overrides = "Stage=\"dev\" FirebaseProjectId=\"collaction-52ca9\" DomainParameter=\"\" SubdomainSuffixParameter=\"\" HostedZoneIdParameter=\"\" AcmCertificateArnParameter=\"\"" From 4c3e35ead8c8f3662c67824326a83717062b1fd8 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 2 Apr 2022 19:11:17 +0200 Subject: [PATCH 37/67] [pull request] removing unnecessary hello world --- pkg/handler/aws/emailContact/main.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/handler/aws/emailContact/main.go b/pkg/handler/aws/emailContact/main.go index cb85840..87ec045 100644 --- a/pkg/handler/aws/emailContact/main.go +++ b/pkg/handler/aws/emailContact/main.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "fmt" "net/http" "github.com/CollActionteam/collaction_backend/internal/contact" @@ -24,8 +23,6 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP } // TODO implement POW verification using nonce (see https://github.com/CollActionteam/collaction_backend/issues/58) - fmt.Println("Hello World") - validate := validator.New() if err := validate.StructCtx(ctx, request); err != nil { body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) From 4c44370a9d3cb75a438f5d41c18b94a93f9bb1f4 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 2 Apr 2022 19:13:32 +0200 Subject: [PATCH 38/67] [pull request] removing some unnecessary comments --- internal/crowdactions/crowdaction.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 804f650..54c2445 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -31,17 +31,11 @@ func NewCrowdactionService(crowdactionRepository CrowdactionManager) Service { return &crowdactionService{crowdactionRepository: crowdactionRepository} } -/** - GET Crowdaction by Id -**/ func (e *crowdactionService) GetCrowdactionById(ctx context.Context, crowdactionID string) (*m.CrowdactionData, error) { fmt.Println("GetCrowdactionById", crowdactionID) return e.crowdactionRepository.GetById(utils.PKCrowdaction, crowdactionID) } -/** - GET Crowdaction by Status -**/ func (e *crowdactionService) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { fmt.Println("GetCrowdactionsByStatus", status, startFrom) return e.crowdactionRepository.GetByStatus(status, startFrom) From 77bed7e9c9ac25a5f6026f2b39c3bcc8386ba3d0 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Fri, 8 Apr 2022 13:57:58 +0200 Subject: [PATCH 39/67] pointing system for the commitments in crowdactions --- docs/api2.yaml | 242 +++++++++++++++++----------------- internal/models/commitment.go | 1 + 2 files changed, 124 insertions(+), 119 deletions(-) diff --git a/docs/api2.yaml b/docs/api2.yaml index 1a8bbad..ee7b2d0 100644 --- a/docs/api2.yaml +++ b/docs/api2.yaml @@ -1,22 +1,22 @@ openapi: 3.0.1 info: title: collaction-dev - version: '1.0' + version: "1.0" servers: - - url: 'https://api{subdomainSuffix}.{domain}/' + - url: "https://api{subdomainSuffix}.{domain}/" variables: subdomainSuffix: - default: '-dev' + default: "-dev" domain: default: collaction.org paths: - '/crowdactions/{crowdactionID}': + "/crowdactions/{crowdactionID}": get: tags: - Crowdaction summary: Get details of a specific crowdaction parameters: - - $ref: '#/components/parameters/ApiVersionParameter' + - $ref: "#/components/parameters/ApiVersionParameter" - name: crowdactionID in: path required: true @@ -30,7 +30,7 @@ paths: type: string format: password responses: - '200': + "200": description: Crowdaction details content: application/json: @@ -48,8 +48,8 @@ paths: type: string example: >- sustainability#food#88615462-2789-4159-8659-2ecfd33ef305 - - $ref: '#/components/schemas/CrowdactionDetails' - '401': + - $ref: "#/components/schemas/CrowdactionDetails" + "401": description: Unauthorized (Invalid password) content: application/json: @@ -63,9 +63,9 @@ paths: type: string example: password: Invalid or missing password - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '404': + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "404": description: Crowdaction not found content: application/json: @@ -79,50 +79,50 @@ paths: type: string example: password: crowdaction does not exist - /crowdactions: - get: - tags: - - Crowdaction - summary: Get list of crowdactions - parameters: - - $ref: '#/components/parameters/ApiVersionParameter' - - name: status - in: query - required: false - schema: - type: string - enum: - - featured - - joinable - - active - - ended - responses: - '200': - description: List of crowdactions - content: - application/json: - schema: - type: object - properties: - status: - type: string - default: success - data: - type: array - items: - allOf: - - type: object - properties: - crowdactionID: - type: string - example: >- - sustainability#food#88615462-2789-4159-8659-2ecfd33ef305 - - $ref: '#/components/schemas/CrowdactionListItem' - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '/crowdactions/{crowdactionID}/participation': + /crowdactions: + get: + tags: + - Crowdaction + summary: Get list of crowdactions + parameters: + - $ref: "#/components/parameters/ApiVersionParameter" + - name: status + in: query + required: false + schema: + type: string + enum: + - featured + - joinable + - active + - ended + responses: + "200": + description: List of crowdactions + content: + application/json: + schema: + type: object + properties: + status: + type: string + default: success + data: + type: array + items: + allOf: + - type: object + properties: + crowdactionID: + type: string + example: >- + sustainability#food#88615462-2789-4159-8659-2ecfd33ef305 + - $ref: "#/components/schemas/CrowdactionListItem" + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "/crowdactions/{crowdactionID}/participation": parameters: - - $ref: '#/components/parameters/ApiVersionParameter' + - $ref: "#/components/parameters/ApiVersionParameter" - name: crowdactionID in: path required: true @@ -133,7 +133,7 @@ paths: - Crowdaction summary: Get existing participation in a particular crowdaction responses: - '200': + "200": description: Success message content: application/json: @@ -144,10 +144,10 @@ paths: type: string default: success data: - $ref: '#/components/schemas/Participation' - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '404': + $ref: "#/components/schemas/Participation" + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "404": description: Not found (Not participating) content: application/json: @@ -168,7 +168,7 @@ paths: - Crowdaction summary: Stop participating in a particular crowdaction responses: - '200': + "200": description: Success message content: application/json: @@ -180,9 +180,9 @@ paths: default: success data: default: null - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '404': + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "404": description: Not found (Not participating) content: application/json: @@ -225,7 +225,7 @@ paths: - no-meat - no-dairy responses: - '201': + "201": description: Success message content: application/json: @@ -237,7 +237,7 @@ paths: default: success data: default: null - '400': + "400": description: Bad request (Invalid commitments) content: application/json: @@ -251,7 +251,7 @@ paths: type: string example: commitments: Required commitment "no-beef" missing - '401': + "401": description: Unauthorized (Invalid password) content: application/json: @@ -265,9 +265,9 @@ paths: type: string example: password: Invalid or missing password - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '409': + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "409": description: Conflict content: application/json: @@ -283,9 +283,9 @@ paths: crowdactionID: already participating security: - FirebaseAuthorizer: [] - '/profiles/{userID}': + "/profiles/{userID}": parameters: - - $ref: '#/components/parameters/ApiVersionParameter' + - $ref: "#/components/parameters/ApiVersionParameter" - name: userID in: path required: true @@ -300,9 +300,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Profile' + $ref: "#/components/schemas/Profile" responses: - '201': + "201": description: Profile was created successfully content: application/json: @@ -314,7 +314,7 @@ paths: status: type: string default: success - '400': + "400": description: Bad request (Validation failed) content: application/json: @@ -328,9 +328,9 @@ paths: type: object example: displayname: Name must not be empty - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '409': + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "409": description: Conflict content: application/json: @@ -355,11 +355,11 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Profile' + $ref: "#/components/schemas/Profile" security: - FirebaseAuthorizer: [] responses: - '200': + "200": description: Profile was updated successfully content: application/json: @@ -371,7 +371,7 @@ paths: status: type: string default: success - '400': + "400": description: Bad request (Validation failed) content: application/json: @@ -385,9 +385,9 @@ paths: type: object example: displayname: Name must not be empty - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '404': + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "404": description: Profile was not found content: application/json: @@ -406,7 +406,7 @@ paths: - Profile summary: View the profile of a user responses: - '200': + "200": description: Profile was found content: application/json: @@ -417,10 +417,10 @@ paths: type: string default: success data: - $ref: '#/components/schemas/Profile' - '403': - $ref: '#/components/responses/UnsupportedClientVersion' - '404': + $ref: "#/components/schemas/Profile" + "403": + $ref: "#/components/responses/UnsupportedClientVersion" + "404": description: Profile was not found content: application/json: @@ -436,13 +436,13 @@ paths: userID: No such profile /upload-profile-picture: parameters: - - $ref: '#/components/parameters/ApiVersionParameter' + - $ref: "#/components/parameters/ApiVersionParameter" get: tags: - Profile summary: Fetch an upload URL (POST) for the profile picture responses: - '200': + "200": description: >- Returns the URL where to upload (PUT) the square png image (250-1024px) @@ -460,13 +460,13 @@ paths: upload_url: type: string format: uri - '403': - $ref: '#/components/responses/UnsupportedClientVersion' + "403": + $ref: "#/components/responses/UnsupportedClientVersion" security: - FirebaseAuthorizer: [] /contact: parameters: - - $ref: '#/components/parameters/ApiVersionParameter' + - $ref: "#/components/parameters/ApiVersionParameter" post: tags: - Other @@ -479,7 +479,7 @@ paths: type: object properties: data: - $ref: '#/components/schemas/Email' + $ref: "#/components/schemas/Email" nonce: type: string example: c2dlcjIzc3NndnJzdnIyM @@ -487,7 +487,7 @@ paths: Nonce for PoW, see http://www.hashcash.org/ (Not yet implemented -> field will be ignored if present) responses: - '200': + "200": description: The status code indicates if the message was successfully sent content: application/json: @@ -499,7 +499,7 @@ paths: default: success data: default: null - '400': + "400": description: Bad request content: application/json: @@ -513,8 +513,8 @@ paths: type: object example: email: Not a valid email address - '403': - $ref: '#/components/responses/UnsupportedClientVersion' + "403": + $ref: "#/components/responses/UnsupportedClientVersion" components: parameters: ApiVersionParameter: @@ -527,7 +527,7 @@ components: schema: type: string pattern: '^[0-9]+\.[0-9]+$' - example: '1.0' + example: "1.0" responses: UnsupportedClientVersion: description: Forbidden (Client version unsupported) @@ -561,22 +561,22 @@ components: subcategory: type: string location: - $ref: '#/components/schemas/Location' + $ref: "#/components/schemas/Location" dates: - $ref: '#/components/schemas/CrowdactionDates' + $ref: "#/components/schemas/CrowdactionDates" password_required: type: boolean commitment_options: type: array items: - $ref: '#/components/schemas/CommitmentOption' + $ref: "#/components/schemas/CommitmentOption" participation: - $ref: '#/components/schemas/Date' + $ref: "#/components/schemas/Date" images: type: object properties: banner: - $ref: '#/components/schemas/Image' + $ref: "#/components/schemas/Image" CrowdactionListItem: type: object properties: @@ -587,18 +587,18 @@ components: subcategory: type: string location: - $ref: '#/components/schemas/Location' + $ref: "#/components/schemas/Location" dates: - $ref: '#/components/schemas/CrowdactionDates' + $ref: "#/components/schemas/CrowdactionDates" password_required: type: boolean participation: - $ref: '#/components/schemas/ParticipationSummary' + $ref: "#/components/schemas/ParticipationSummary" images: type: object properties: card: - $ref: '#/components/schemas/Image' + $ref: "#/components/schemas/Image" CrowdactionDates: type: object description: >- @@ -606,11 +606,11 @@ components: latter properties: start: - $ref: '#/components/schemas/Date' + $ref: "#/components/schemas/Date" end: - $ref: '#/components/schemas/Date' + $ref: "#/components/schemas/Date" join_before: - $ref: '#/components/schemas/Date' + $ref: "#/components/schemas/Date" Location: type: object properties: @@ -629,6 +629,9 @@ components: label: type: string example: Becoming vegetarian + points: + type: int + example: 30 description: type: string example: I will not eat any meat from any animal (including fish). @@ -638,15 +641,16 @@ components: Commitments that are included in (and required by) this commitment. They can also be individually selected items: - $ref: '#/components/schemas/CommitmentOption' + $ref: "#/components/schemas/CommitmentOption" example: id: no-beef label: Not eating beef description: I will avoid eating beef (Goodbye stake). + points: 30 Date: type: string pattern: '\d{4}-\d{2}-\d{2}' - example: '2021-11-28' + example: "2021-11-28" ParticipationSummary: type: object properties: @@ -668,12 +672,12 @@ components: properties: url: type: string - example: 'https://picsum.photos/300/200' + example: "https://picsum.photos/300/200" format: uri blur_hash: type: string example: LEHV6nWB2yk8pyo0adR*.7kCMdnj - description: '(see https://blurha.sh/)' + description: "(see https://blurha.sh/)" Participation: type: object properties: @@ -684,7 +688,7 @@ components: description: Displayname of the user crowdactionID: type: string - example: 'sustainability#food#88615462-2789-4159-8659-2ecfd33ef305' + example: "sustainability#food#88615462-2789-4159-8659-2ecfd33ef305" title: type: string description: Title of the crowdactions @@ -697,7 +701,7 @@ components: - no-dairy description: Array of commitment ids date: - $ref: '#/components/schemas/Date' + $ref: "#/components/schemas/Date" Profile: type: object properties: @@ -705,7 +709,7 @@ components: type: string example: Max Murphy location: - $ref: '#/components/schemas/Location' + $ref: "#/components/schemas/Location" bio: type: string example: >- @@ -723,7 +727,7 @@ components: example: Hello world message: type: string - example: 'Please respond to this email :)' + example: "Please respond to this email :)" app_version: type: string pattern: '^(?:ios|android) [0-9]+\.[0-9]+\.[0-9]+\+[0-9]+$' diff --git a/internal/models/commitment.go b/internal/models/commitment.go index e8dac0c..46eec0d 100644 --- a/internal/models/commitment.go +++ b/internal/models/commitment.go @@ -5,4 +5,5 @@ type CommitmentOption struct { Label string `json:"label"` Description string `json:"description"` Requires []CommitmentOption `json:"requires,omitempty"` + Points int `json:"points"` } From 17cd6fbdc22e35a4d2a5b77f4257464b49e12b6f Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 11 Jun 2022 19:15:26 +0200 Subject: [PATCH 40/67] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 29442c16bfa16b27c9787140fbdaba35c43d8f03 Merge: 9a473b1 fd30c56 Author: Ed Reinoso Date: Sat Jun 11 19:03:51 2022 +0200 Merge branch 'development' into feat/gh-73/crowdactions commit 9a473b13e76d1e6bf13b25362f94639a2f80779c Author: Ed Reinoso Date: Sat Jun 11 19:00:07 2022 +0200 returning crowdaction object commit fd30c5662d73732c2d67fe2a30535db7234bc3b8 Merge: d189c2d 15a4d6e Author: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> Date: Wed May 18 09:40:16 2022 +0200 Merge pull request #132 from CollActionteam/feat/gh-73/crowdactions Feat/gh 73/crowdactions commit 15a4d6eb6630ac2b5d9ad48f09a654d785a1214d Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Tue May 17 23:26:57 2022 +0200 comment out cms endpoint (revisit later) commit 9f8fb11dcbe8e0755e62313df742d643bc324d14 Merge: 141e144 d189c2d Author: Ed Reinoso Date: Sun May 15 09:28:12 2022 +0200 Merge branch 'development' of github.com:CollActionteam/collaction_backend into feat/gh-73/crowdactions commit 141e1446857696b8e905ed7a826b0cdf3ad9496d Author: Ed Reinoso Date: Sun May 15 09:24:31 2022 +0200 ⚡️ scan operations on crowdactions commit 2dd48b265b27a598f7429b1885f816ab16dfb9d3 Author: Ed Reinoso Date: Sun May 15 09:23:20 2022 +0200 ⚡️ mock create crowdaction commit d189c2d41cd764e5505841045013cf87f0e09983 Merge: 3fb6e82 dce91c7 Author: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> Date: Thu May 5 21:50:41 2022 +0200 Merge pull request #129 from CollActionteam/fix/contact-form-unit-tests Expect recipient also as sender in tests commit dce91c7d9eff6545a58beec10953d657be882b17 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Thu May 5 21:43:56 2022 +0200 Expect recipient also as sender in tests commit 3fb6e823054d044b274e5f35008cc7b8155f803c Merge: 1366e1e 7a51f51 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Thu May 5 21:31:00 2022 +0200 Merge pull request #128 from CollActionteam/fix/email-contact-not-registered Use registered address as both sender and recipient commit 7a51f514766ee15b64d4279783444c5342c9fe78 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Thu May 5 21:29:15 2022 +0200 Use registered address as both sender and recipient commit 1366e1e43ddd2d9d0f42c6117ff7a9760f277ecb Merge: 93bb124 8b63733 Author: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> Date: Thu May 5 20:50:42 2022 +0200 Merge pull request #126 from CollActionteam/fix/app-version-regex Fixed regex commit 8b63733108ca752febf1fbd008edf08c9593cd99 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Thu May 5 20:49:57 2022 +0200 Fixed regex s. https://regexr.com/6l215 commit 93bb124f0ca0dfcbe186403b030bbe0df2124b98 Author: Ed Reinoso Date: Sun Apr 17 23:15:50 2022 +0200 Feat/gh 73/crowdactions (#119) * 🚀 crowdaction hex refactoring init * 🚧 dynamodb manager repository, pt1: init * ⚡️ launching own sam config * 🚧 [crowdaction] deployed first function on to aws * 🚧 [crowdaction] removing extra copy of dynamo repository * 🚧 [crowdaction] init model and validation on request * 🚧 [crowdaction] changed the model function names * 🚧 [crowdaction] working on internal and handler * 🚧 [crowdaction] simple version of GET request by ID * 🚧 [crowdaction] testing GET request by ID * 🚧 [crowdaction] creating external function to GET crowdaction by ID * 🚧 [crowdaction] including query function in ddb repository * 🚧 [crowdaction] initial code base for GET crowdactions by status * 🚧 [crowdaction] cleaning up, commitment options * 🚧 [crowdaction] including the mock repository for dynamo and crowdaction * 🚧 [crowdaction] modifying the mock repository to include GetCrowdactionByStatus * 🚧 [crowdaction] removed unnecessary comments, per the feedback on pull request * [pull request] removing samconfig file from history * [pull request] ignoring samconfig file as per the pull request * [pull request] modified naming for the internal interface * [pull request] getting rid of useless else statement * [pull request] removing dynamodb dependencies in logic * [pull request] including mock repository and crowdaction test * [pull request] cleaning up some unnecessary lines * [pull request] separating repository concerns * [pull request] modifying test cases with new repository structure * [pull request] changing dynamo repository call from crowdaction main handler * [pull request] changing parameters to pass unit test case * [pull request] changing crowdactionID from test case * [pull request] changing method call for crowdaction test * [pull request] fixing parameter issue in crowdaction_test * [pull request] testing issue with the args.get(x) call in mock/dynamo repository * [pull request] including Mock in each of the function calls from the dynamo repository * [pull request] modifying test cases for crowdaction * [pull request] changes done based on feedback [pull request] ignoring samconfig file as per the pull request [pull request] modified naming for the internal interface [pull request] getting rid of useless else statement [pull request] removing dynamodb dependencies in logic [pull request] including mock repository and crowdaction test [pull request] cleaning up some unnecessary lines [pull request] separating repository concerns [pull request] modifying test cases with new repository structure [pull request] changing dynamo repository call from crowdaction main handler [pull request] changing parameters to pass unit test case [pull request] changing crowdactionID from test case [pull request] changing method call for crowdaction test [pull request] fixing parameter issue in crowdaction_test [pull request] testing issue with the args.get(x) call in mock/dynamo repository [pull request] including Mock in each of the function calls from the dynamo repository [pull request] modifying test cases for crowdaction * [pull request] removing unnecessary hello world * [pull request] removing some unnecessary comments * final changes before merging This commit starts by containing the separation between the post and the get methods that will be used for handling crowdactions * removing a duplicate package When merged, the net/http packe was imported twice by accident * [pull request] cleaning up some final comments This should be the last commit before merging to development. The implementation includes the initial basis for the /post endpoint to create crowdactions from the CMS. The continuation of this task (/post) should be done ideally in the CMS task (up for a discussion, of course) but could expanded somewhere else for other purposes. For example, the badge issue may implement a very rudimentary version of this /post crowdaction for testing purposes. * changing the crowdaction test case commit 854d2bc3f867ac5b5b658cbec5add715dfee7e86 Author: Ed Reinoso Date: Sun Apr 17 14:28:41 2022 +0200 changing the crowdaction test case commit 188f7b30138be6e8b19a290cff04a3d59472cdd7 Author: Ed Reinoso Date: Sun Apr 17 11:35:33 2022 +0200 [pull request] cleaning up some final comments This should be the last commit before merging to development. The implementation includes the initial basis for the /post endpoint to create crowdactions from the CMS. The continuation of this task (/post) should be done ideally in the CMS task (up for a discussion, of course) but could expanded somewhere else for other purposes. For example, the badge issue may implement a very rudimentary version of this /post crowdaction for testing purposes. commit e7a3d2a0ecae92c6720835ee2263b0821126a8eb Merge: eb3b973 9ac0b81 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Sat Apr 16 19:57:25 2022 +0200 Merge pull request #123 from CollActionteam/Automated-security-scanning Automated-security-scanning commit f1e73065fbd24f97243087b0dd0687f6469ac86c Author: Ed Reinoso Date: Fri Apr 15 21:25:11 2022 +0200 removing a duplicate package When merged, the net/http packe was imported twice by accident commit f8e0936d500005cc781c94f4e61ad1095dde9225 Merge: b9dd8b7 eb3b973 Author: Ed Reinoso Date: Fri Apr 15 21:23:54 2022 +0200 Merge branch 'development' of github.com:CollActionteam/collaction_backend into feat/gh-73/crowdactions # Conflicts: # pkg/handler/aws/emailContact/main.go commit b9dd8b763d6d46f8f1f2050a29a94486560b174f Author: Ed Reinoso Date: Fri Apr 15 21:18:53 2022 +0200 final changes before merging This commit starts by containing the separation between the post and the get methods that will be used for handling crowdactions commit 9ac0b817b41a89e25d804bc9f5bf8b8f4a30ba90 Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Fri Apr 15 12:04:21 2022 +0200 Create codeql-analysis.yml commit eb3b97386256218f92800e2b16a017190f0da017 Merge: 8626468 824b5ed Author: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Date: Mon Apr 11 01:07:09 2022 +0200 Merge pull request #122 from CollActionteam/bugfix/contact_valication fix app version validation commit 8626468ddd48f51e4b58d3a7375bc8ebcf9578a7 Author: Sobowale-Olayiwola <71639457+Sobowale-Olayiwola@users.noreply.github.com> Date: Sun Apr 10 22:57:37 2022 +0100 [Refactoring] [Arch] Upload Profile Picture (#77) * Added interfaces for profile images upload * Implmented repository functions * created handler for profile pics upload * Updated code based on reviews * Removed comments based on reviews * Added mock and test * Updated template.yaml * Removed deferred recovery function call and updated error msg * Update pkg/repository/aws/uploadProfilePictureManager.go Co-authored-by: Mohammad Rajabloo * Fixed changes regarding review Co-authored-by: Ruben Horn <5367484+rubenhorn@users.noreply.github.com> Co-authored-by: Mohammad Rajabloo commit 824b5ed4bba00e409baa2a418bd418de0e369ef5 Author: Mohammad Rajabloo Date: Mon Apr 11 00:42:43 2022 +0430 fix app version validation --- .github/workflows/codeql-analysis.yml | 70 +++++++++++ docs/api2.yaml | 12 -- internal/contact/email.go | 7 +- internal/contact/email_test.go | 4 +- internal/crowdactions/crowdaction.go | 20 ++- internal/crowdactions/crowdaction_test.go | 5 +- internal/models/contact.go | 31 ++++- internal/models/crowdaction.go | 7 +- internal/uploads/profilePicture.go | 23 ++++ internal/uploads/profilePicture_test.go | 64 ++++++++++ pkg/handler/aws/crowdaction/crowdaction.go | 114 ++++++++++++++++++ pkg/handler/aws/crowdaction/main.go | 68 ++--------- pkg/handler/aws/emailContact/main.go | 7 +- pkg/handler/aws/uploadProfilePicture/main.go | 43 +++++++ pkg/mocks/repository/dynamoManager.go | 12 ++ .../repository/uploadProfilePictureManager.go | 20 +++ pkg/repository/aws/crowdactionManager.go | 81 +++++++++++-- pkg/repository/aws/dynamo.go | 17 +++ .../aws/uploadProfilePictureManager.go | 38 ++++++ template.yaml | 11 +- 20 files changed, 546 insertions(+), 108 deletions(-) create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 internal/uploads/profilePicture.go create mode 100644 internal/uploads/profilePicture_test.go create mode 100644 pkg/handler/aws/crowdaction/crowdaction.go create mode 100644 pkg/handler/aws/uploadProfilePicture/main.go create mode 100644 pkg/mocks/repository/uploadProfilePictureManager.go create mode 100644 pkg/repository/aws/uploadProfilePictureManager.go diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..30d108a --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ development, master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ development ] + schedule: + - cron: '0 8 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go', 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/docs/api2.yaml b/docs/api2.yaml index 8386867..601a626 100644 --- a/docs/api2.yaml +++ b/docs/api2.yaml @@ -84,18 +84,6 @@ paths: tags: - Crowdaction summary: Get list of crowdactions - parameters: - - $ref: "#/components/parameters/ApiVersionParameter" - - name: status - in: query - required: false - schema: - type: string - enum: - - featured - - joinable - - active - - ended responses: "200": description: List of crowdactions diff --git a/internal/contact/email.go b/internal/contact/email.go index 2bc33b6..4629546 100644 --- a/internal/contact/email.go +++ b/internal/contact/email.go @@ -3,6 +3,7 @@ package contact import ( "context" "fmt" + "github.com/CollActionteam/collaction_backend/internal/constants" "github.com/CollActionteam/collaction_backend/internal/models" ) @@ -33,16 +34,16 @@ func NewContactService(emailRepository EmailRepository, configManager ConfigMana } func (e *contact) SendEmail(ctx context.Context, req models.EmailContactRequest) error { - recipient, err := e.configManager.GetParameter(fmt.Sprintf(constants.RecipientEmail, e.stage)) + senderRecipient, err := e.configManager.GetParameter(fmt.Sprintf(constants.RecipientEmail, e.stage)) if err != nil { return err } return e.emailRepository.Send(ctx, models.EmailData{ - Recipient: recipient, + Recipient: senderRecipient, Message: fmt.Sprintf(EmailMessageFormat, req.Data.Message, Separator, req.Data.AppVersion), Subject: req.Data.Subject, - Sender: req.Data.Email, + Sender: senderRecipient, ReplyEmail: req.Data.Email, }) } diff --git a/internal/contact/email_test.go b/internal/contact/email_test.go index da3e053..36f0153 100644 --- a/internal/contact/email_test.go +++ b/internal/contact/email_test.go @@ -28,7 +28,7 @@ func TestContact_SendEmail(t *testing.T) { Recipient: recipientValue, Message: fmt.Sprintf(contact.EmailMessageFormat, emailRequest.Data.Message, contact.Separator, emailRequest.Data.AppVersion), Subject: emailRequest.Data.Subject, - Sender: emailRequest.Data.Email, + Sender: recipientValue, ReplyEmail: emailRequest.Data.Email, } @@ -52,7 +52,7 @@ func TestContact_SendEmail(t *testing.T) { Recipient: recipientValue, Message: fmt.Sprintf(contact.EmailMessageFormat, emailRequest.Data.Message, contact.Separator, emailRequest.Data.AppVersion), Subject: emailRequest.Data.Subject, - Sender: emailRequest.Data.Email, + Sender: recipientValue, ReplyEmail: emailRequest.Data.Email, } diff --git a/internal/crowdactions/crowdaction.go b/internal/crowdactions/crowdaction.go index 54c2445..3bc5b34 100644 --- a/internal/crowdactions/crowdaction.go +++ b/internal/crowdactions/crowdaction.go @@ -2,19 +2,22 @@ package crowdaction import ( "context" - "fmt" m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" ) type Service interface { + GetAllCrowdactions(ctx context.Context) ([]m.CrowdactionData, error) GetCrowdactionById(ctx context.Context, crowdactionId string) (*m.CrowdactionData, error) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) + RegisterCrowdaction(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) } type CrowdactionManager interface { + GetAll() ([]m.CrowdactionData, error) GetById(pk string, crowdactionId string) (*m.CrowdactionData, error) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) + Register(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) } const ( @@ -31,12 +34,23 @@ func NewCrowdactionService(crowdactionRepository CrowdactionManager) Service { return &crowdactionService{crowdactionRepository: crowdactionRepository} } +func (e *crowdactionService) GetAllCrowdactions(ctx context.Context) ([]m.CrowdactionData, error) { + return e.crowdactionRepository.GetAll() +} + func (e *crowdactionService) GetCrowdactionById(ctx context.Context, crowdactionID string) (*m.CrowdactionData, error) { - fmt.Println("GetCrowdactionById", crowdactionID) return e.crowdactionRepository.GetById(utils.PKCrowdaction, crowdactionID) } func (e *crowdactionService) GetCrowdactionsByStatus(ctx context.Context, status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { - fmt.Println("GetCrowdactionsByStatus", status, startFrom) return e.crowdactionRepository.GetByStatus(status, startFrom) } + +func (e *crowdactionService) RegisterCrowdaction(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) { + res, err := e.crowdactionRepository.Register(ctx, payload) + + if err != nil { + return res, err + } + return res, err +} diff --git a/internal/crowdactions/crowdaction_test.go b/internal/crowdactions/crowdaction_test.go index 5ae810a..7818ffa 100644 --- a/internal/crowdactions/crowdaction_test.go +++ b/internal/crowdactions/crowdaction_test.go @@ -2,7 +2,6 @@ package crowdaction_test import ( "context" - "fmt" "testing" cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" @@ -25,9 +24,7 @@ func TestCrowdaction_GetCrowdactionById(t *testing.T) { service := cwd.NewCrowdactionService(dynamoRepository) - crowdaction, err := service.GetCrowdactionById(ctx, crowdactionID) - - fmt.Println("Hello world", crowdaction) + _, err := service.GetCrowdactionById(ctx, crowdactionID) as.NoError(err) diff --git a/internal/models/contact.go b/internal/models/contact.go index 750fc32..0306501 100644 --- a/internal/models/contact.go +++ b/internal/models/contact.go @@ -1,16 +1,23 @@ package models +import ( + "context" + "regexp" + + "github.com/CollActionteam/collaction_backend/utils" + "github.com/go-playground/validator/v10" +) + type EmailContactRequest struct { Data EmailRequestData `json:"data" validate:"required"` Nonce string `json:"nonce"` } type EmailRequestData struct { - Email string `json:"email" validate:"required,email" binding:"required"` - Subject string `json:"subject" validate:"required,lte=50" binding:"required"` - Message string `json:"message" validate:"required,lte=500" binding:"required"` - //TODO 11.01.22 mrsoftware: fix regx - AppVersion string `json:"app_version" validate:"required" binding:"required"` // ,regexp=^(?:ios|android) [0-9]+\\.[0-9]+\\.[0-9]+\\+[0-9]+$ + Email string `json:"email" validate:"required,email" binding:"required"` + Subject string `json:"subject" validate:"required,lte=50" binding:"required"` + Message string `json:"message" validate:"required,lte=500" binding:"required"` + AppVersion string `json:"app_version" validate:"required" binding:"required"` } type EmailData struct { @@ -20,3 +27,17 @@ type EmailData struct { Sender string ReplyEmail string } + +func (e EmailContactRequest) Validate(ctx context.Context) validator.ValidationErrorsTranslations { + validate := validator.New() + if err := validate.StructCtx(ctx, e); err != nil { + return utils.ValidationResponse(err, validate) + } + + reg := regexp.MustCompile(`^(?:ios|android) [0-9]+\.[0-9]+\.[0-9]+\+[0-9]+$`) + if match := reg.MatchString(e.Data.AppVersion); !match { + return validator.ValidationErrorsTranslations{"err": "app version is not valid"} + } + + return nil +} diff --git a/internal/models/crowdaction.go b/internal/models/crowdaction.go index 67ec0c9..15ae68f 100644 --- a/internal/models/crowdaction.go +++ b/internal/models/crowdaction.go @@ -15,18 +15,19 @@ type CrowdactionImages struct { } type CrowdactionData struct { - CrowdactionID string `json:"crowdactionID"` Title string `json:"title"` Description string `json:"description"` Category string `json:"category"` Subcategory string `json:"subcategory"` Location string `json:"location"` - DateStart string `json:"date_start"` DateEnd string `json:"date_end"` DateLimitJoin string `json:"date_limit_join"` PasswordJoin string `json:"password_join"` + Images CrowdactionImages `json:"images"` + CrowdactionID string `json:"crowdactionID"` + Badges []int `json:"badges"` + DateStart string `json:"date_start"` ParticipationCount int `json:"participant_count"` TopParticipants []CrowdactionParticipant `json:"top_participants"` - Images CrowdactionImages `json:"images"` CommitmentOptions []CommitmentOption `json:"commitment_options"` } diff --git a/internal/uploads/profilePicture.go b/internal/uploads/profilePicture.go new file mode 100644 index 0000000..5429b64 --- /dev/null +++ b/internal/uploads/profilePicture.go @@ -0,0 +1,23 @@ +package uploads + +import "context" + +type ProfileImageUploadRepository interface { + GetUploadUrl(ctx context.Context, ext string, userID string) (string, error) +} + +type Service interface { + GetUploadUrl(ctx context.Context, ext string, userID string) (string, error) +} + +type image struct { + imageUploadRepository ProfileImageUploadRepository +} + +func NewProfileImageUploadService(profileImageUploadRepo ProfileImageUploadRepository) Service { + return &image{imageUploadRepository: profileImageUploadRepo} +} + +func (i *image) GetUploadUrl(ctx context.Context, ext string, userID string) (string, error) { + return i.imageUploadRepository.GetUploadUrl(ctx, ext, userID) +} diff --git a/internal/uploads/profilePicture_test.go b/internal/uploads/profilePicture_test.go new file mode 100644 index 0000000..fdf32cf --- /dev/null +++ b/internal/uploads/profilePicture_test.go @@ -0,0 +1,64 @@ +package uploads_test + +import ( + "context" + "errors" + "testing" + + "github.com/CollActionteam/collaction_backend/internal/uploads" + "github.com/CollActionteam/collaction_backend/pkg/mocks/repository" + "github.com/stretchr/testify/assert" +) + +func TestProfile_GetUploadUrl(t *testing.T) { + as := assert.New(t) + imageUploadRepository := &repository.ProfilePicture{} + + t.Run("happy path", func(t *testing.T) { + ext := "jpeg" + userID := "1" + service := uploads.NewProfileImageUploadService(imageUploadRepository) + + imageUploadRepository.On("GetUploadUrl", context.Background(), ext, userID).Return("https://sample-user-url-generated", nil).Once() + url, err := service.GetUploadUrl(context.Background(), ext, userID) + as.Equal("https://sample-user-url-generated", url) + as.NoError(err) + imageUploadRepository.AssertExpectations(t) + }) + + t.Run("input error: userID empty", func(t *testing.T) { + ext := "jpeg" + userID := "" + service := uploads.NewProfileImageUploadService(imageUploadRepository) + + imageUploadRepository.On("GetUploadUrl", context.Background(), ext, userID).Return("", errors.New("user not found")).Once() + url, err := service.GetUploadUrl(context.Background(), ext, userID) + as.Equal("", url) + as.Error(err) + imageUploadRepository.AssertExpectations(t) + }) + + t.Run("input error: invalid image format", func(t *testing.T) { + ext := "agsgfh" + userID := "1" + service := uploads.NewProfileImageUploadService(imageUploadRepository) + + imageUploadRepository.On("GetUploadUrl", context.Background(), ext, userID).Return("", errors.New("unknown file format")).Once() + url, err := service.GetUploadUrl(context.Background(), ext, userID) + as.Equal("", url) + as.Error(err) + imageUploadRepository.AssertExpectations(t) + }) + + t.Run("system error", func(t *testing.T) { + ext := "jpeg" + userID := "1" + service := uploads.NewProfileImageUploadService(imageUploadRepository) + + imageUploadRepository.On("GetUploadUrl", context.Background(), ext, userID).Return("", errors.New("something failed")).Once() + url, err := service.GetUploadUrl(context.Background(), ext, userID) + as.Equal("", url) + as.Error(err) + imageUploadRepository.AssertExpectations(t) + }) +} diff --git a/pkg/handler/aws/crowdaction/crowdaction.go b/pkg/handler/aws/crowdaction/crowdaction.go new file mode 100644 index 0000000..83e7deb --- /dev/null +++ b/pkg/handler/aws/crowdaction/crowdaction.go @@ -0,0 +1,114 @@ +package main + +import ( + "context" + "encoding/json" + "net/http" + + cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" + m "github.com/CollActionteam/collaction_backend/internal/models" + hnd "github.com/CollActionteam/collaction_backend/pkg/handler" + awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" + "github.com/CollActionteam/collaction_backend/utils" + "github.com/aws/aws-lambda-go/events" + "github.com/go-playground/validator/v10" +) + +type CrowdactionHandler struct { + service cwd.Service +} + +func NewCrowdactionHandler() *CrowdactionHandler { + crowdactionParticipation := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) + return &CrowdactionHandler{service: cwd.NewCrowdactionService(crowdactionParticipation)} +} + +func (c *CrowdactionHandler) createCrowdaction(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { + var payload m.CrowdactionData + if err := json.Unmarshal([]byte(req.Body), &payload); err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + + res, err := c.service.RegisterCrowdaction(ctx, payload) + + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + + } + // return call to client + body, _ := json.Marshal(hnd.Response{Status: hnd.StatusSuccess, Data: res}) + + return events.APIGatewayV2HTTPResponse{ + Body: string(body), + StatusCode: http.StatusOK, + }, nil +} + +/** + Gateway for all the GET crowdaction methods +**/ + +func (c *CrowdactionHandler) getCrowdaction(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { + crowdactionID := req.PathParameters["crowdactionID"] + var request m.CrowdactionRequest + + validate := validator.New() + if err := validate.StructCtx(ctx, request); err != nil { + body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) + return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil + } + + if crowdactionID == "" && req.QueryStringParameters["status"] != "" { // get only by status + status := req.QueryStringParameters["status"] + return c.getCrowdactionsByStatus(ctx, status) + } else if crowdactionID == "" { // to get all crowdactions + return c.getAllCrowdactions(ctx) + } + + return c.getCrowdactionByID(ctx, crowdactionID) // get crowdaction by id +} + +func (c *CrowdactionHandler) getAllCrowdactions(ctx context.Context) (events.APIGatewayV2HTTPResponse, error) { + getCrowdactions, err := c.service.GetAllCrowdactions(ctx) + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + + jsonPayload, _ := json.Marshal(getCrowdactions) + + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil +} + +func (c *CrowdactionHandler) getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { + getCrowdaction, err := c.service.GetCrowdactionById(ctx, crowdactionID) + + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + if getCrowdaction == nil { + return utils.CreateMessageHttpResponse(http.StatusNotFound, "Crowdaction not found!"), nil + } + + jsonPayload, _ := json.Marshal(getCrowdaction) + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil +} + +func (c *CrowdactionHandler) getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { + getCrowdactions, err := c.service.GetCrowdactionsByStatus(ctx, status, nil) + + if err != nil { + return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil + } + jsonPayload, _ := json.Marshal(getCrowdactions) + + return events.APIGatewayV2HTTPResponse{ + Body: string(jsonPayload), + StatusCode: http.StatusOK, + }, nil +} diff --git a/pkg/handler/aws/crowdaction/main.go b/pkg/handler/aws/crowdaction/main.go index dc32435..61a0ae7 100644 --- a/pkg/handler/aws/crowdaction/main.go +++ b/pkg/handler/aws/crowdaction/main.go @@ -2,75 +2,27 @@ package main import ( "context" - "encoding/json" "net/http" + "strings" - cwd "github.com/CollActionteam/collaction_backend/internal/crowdactions" - "github.com/CollActionteam/collaction_backend/internal/models" - hnd "github.com/CollActionteam/collaction_backend/pkg/handler" - awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" - "github.com/go-playground/validator/v10" ) -func getCrowdactionByID(ctx context.Context, crowdactionID string) (events.APIGatewayV2HTTPResponse, error) { - dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) - getCrowdaction, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionById(ctx, crowdactionID) - - if err != nil { - return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } - if getCrowdaction == nil { - return utils.CreateMessageHttpResponse(http.StatusNotFound, "not participating"), nil - } - - jsonPayload, _ := json.Marshal(getCrowdaction) - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil -} - -func getCrowdactionsByStatus(ctx context.Context, status string) (events.APIGatewayV2HTTPResponse, error) { - dynamoRepository := awsRepository.NewCrowdaction(awsRepository.NewDynamo()) - getCrowdactions, err := cwd.NewCrowdactionService(dynamoRepository).GetCrowdactionsByStatus(ctx, status, nil) - - if err != nil { - return utils.CreateMessageHttpResponse(http.StatusInternalServerError, err.Error()), nil - } - jsonPayload, _ := json.Marshal(getCrowdactions) - - return events.APIGatewayV2HTTPResponse{ - Body: string(jsonPayload), - StatusCode: http.StatusOK, - }, nil -} - func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { - crowdactionID := req.PathParameters["crowdactionID"] - var request models.CrowdactionRequest - - validate := validator.New() - if err := validate.StructCtx(ctx, request); err != nil { - body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) - return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil - } - - if crowdactionID == "" { - status := req.QueryStringParameters["status"] - return getCrowdactionsByStatus(ctx, status) + method := strings.ToLower(req.RequestContext.HTTP.Method) + + switch method { + case "post": + return NewCrowdactionHandler().createCrowdaction(ctx, req) + case "get": + return NewCrowdactionHandler().getCrowdaction(ctx, req) + default: + return utils.CreateMessageHttpResponse(http.StatusNotImplemented, "not implemented"), nil } - - return getCrowdactionByID(ctx, crowdactionID) } func main() { lambda.Start(handler) } - -func errToResponse(err error, code int) events.APIGatewayV2HTTPResponse { - msg, _ := json.Marshal(map[string]string{"message": err.Error()}) - return events.APIGatewayV2HTTPResponse{Body: string(msg), StatusCode: code} -} diff --git a/pkg/handler/aws/emailContact/main.go b/pkg/handler/aws/emailContact/main.go index 87ec045..fb699e2 100644 --- a/pkg/handler/aws/emailContact/main.go +++ b/pkg/handler/aws/emailContact/main.go @@ -9,11 +9,9 @@ import ( "github.com/CollActionteam/collaction_backend/internal/models" hnd "github.com/CollActionteam/collaction_backend/pkg/handler" awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" - "github.com/CollActionteam/collaction_backend/utils" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go/aws/session" - "github.com/go-playground/validator/v10" ) func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { @@ -23,9 +21,8 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.AP } // TODO implement POW verification using nonce (see https://github.com/CollActionteam/collaction_backend/issues/58) - validate := validator.New() - if err := validate.StructCtx(ctx, request); err != nil { - body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": utils.ValidationResponse(err, validate)}}) + if err := request.Validate(ctx); err != nil { + body, _ := json.Marshal(hnd.Response{Status: hnd.StatusFail, Data: map[string]interface{}{"error": err}}) return events.APIGatewayV2HTTPResponse{Body: string(body), StatusCode: http.StatusBadRequest}, nil } diff --git a/pkg/handler/aws/uploadProfilePicture/main.go b/pkg/handler/aws/uploadProfilePicture/main.go new file mode 100644 index 0000000..7309ce5 --- /dev/null +++ b/pkg/handler/aws/uploadProfilePicture/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/CollActionteam/collaction_backend/auth" + "github.com/CollActionteam/collaction_backend/internal/uploads" + awsRepository "github.com/CollActionteam/collaction_backend/pkg/repository/aws" + "github.com/aws/aws-lambda-go/events" + "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-sdk-go/aws/session" +) + +func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (res events.APIGatewayV2HTTPResponse, err error) { + usrInf, err := auth.ExtractUserInfo(req) + if err != nil { + res = events.APIGatewayV2HTTPResponse{StatusCode: http.StatusForbidden, Body: "user not authorized"} + return res, err + } + + userID := usrInf.UserID() + sess := session.Must(session.NewSession()) + profileImageUploadRepo := awsRepository.NewProfilePicture(sess) + + strUrl, err := uploads.NewProfileImageUploadService(profileImageUploadRepo).GetUploadUrl(ctx, "png", userID) + if err != nil { + res = events.APIGatewayV2HTTPResponse{StatusCode: http.StatusInternalServerError, Body: "error generating link"} + return res, err + } + + response, _ := json.Marshal(map[string]interface{}{"upload_url": strUrl}) + + return events.APIGatewayV2HTTPResponse{ + StatusCode: http.StatusOK, + Body: string(response), + }, nil +} + +func main() { + lambda.Start(handler) +} diff --git a/pkg/mocks/repository/dynamoManager.go b/pkg/mocks/repository/dynamoManager.go index 3d37bab..e5a725a 100644 --- a/pkg/mocks/repository/dynamoManager.go +++ b/pkg/mocks/repository/dynamoManager.go @@ -1,6 +1,8 @@ package repository import ( + "context" + m "github.com/CollActionteam/collaction_backend/internal/models" "github.com/CollActionteam/collaction_backend/utils" "github.com/stretchr/testify/mock" @@ -10,6 +12,11 @@ type Dynamo struct { mock.Mock } +func (d *Dynamo) GetAll() ([]m.CrowdactionData, error) { + args := d.Mock.Called() + return args.Get(0).([]m.CrowdactionData), args.Error(1) +} + func (d *Dynamo) GetById(pk string, sk string) (*m.CrowdactionData, error) { args := d.Mock.Called(pk, sk) return args.Get(0).(*m.CrowdactionData), args.Error(1) @@ -19,3 +26,8 @@ func (d *Dynamo) GetByStatus(filterCond string, startFrom *utils.PrimaryKey) ([] args := d.Mock.Called(filterCond, startFrom) return args.Get(0).([]m.CrowdactionData), args.Error(1) } + +func (d *Dynamo) Register(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) { + d.Mock.Called(payload) + return &payload, nil +} diff --git a/pkg/mocks/repository/uploadProfilePictureManager.go b/pkg/mocks/repository/uploadProfilePictureManager.go new file mode 100644 index 0000000..f3098f4 --- /dev/null +++ b/pkg/mocks/repository/uploadProfilePictureManager.go @@ -0,0 +1,20 @@ +package repository + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type ProfilePicture struct { + mock.Mock +} + +func (p *ProfilePicture) GetUploadUrl(ctx context.Context, ext string, userID string) (string, error) { + outputs := p.Mock.Called(ctx, ext, userID) + + uploadUrl := outputs.String(0) + err := outputs.Error(1) + + return uploadUrl, err +} diff --git a/pkg/repository/aws/crowdactionManager.go b/pkg/repository/aws/crowdactionManager.go index fb29b7b..3f69fc5 100644 --- a/pkg/repository/aws/crowdactionManager.go +++ b/pkg/repository/aws/crowdactionManager.go @@ -1,7 +1,10 @@ package aws import ( + "context" "fmt" + "math/rand" + "time" "github.com/CollActionteam/collaction_backend/internal/constants" m "github.com/CollActionteam/collaction_backend/internal/models" @@ -11,8 +14,11 @@ import ( ) type Crowdaction interface { + GetAll() ([]m.CrowdactionData, error) GetById(pk string, sk string) (*m.CrowdactionData, error) GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) + Register(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) + // Register(ctx context.Context, payload m.CrowdactionData) error } const ( @@ -21,6 +27,11 @@ const ( KeyDateJoinBefore = "date_limit_join" ) +const charset = "abcdefghijklmnopqrstuvwxyz0123456789" + +var seededRand *rand.Rand = rand.New( + rand.NewSource(time.Now().UnixNano())) + type crowdaction struct { dbClient *Dynamo } @@ -29,9 +40,18 @@ func NewCrowdaction(dynamo *Dynamo) Crowdaction { return &crowdaction{dbClient: dynamo} } -/** - GET Crowdaction by Id -**/ +func StringWithCharset(length int, charset string) string { + b := make([]byte, length) + for i := range b { + b[i] = charset[seededRand.Intn(len(charset))] + } + return string(b) +} + +func RandomIDPrefix(length int) string { + return StringWithCharset(length, charset) +} + func (s *crowdaction) GetById(pk string, sk string) (*m.CrowdactionData, error) { item, err := s.dbClient.GetDBItem(constants.TableName, pk, sk) @@ -45,9 +65,31 @@ func (s *crowdaction) GetById(pk string, sk string) (*m.CrowdactionData, error) return &c, err } -/** - GET Crowdaction by Status -**/ +func (s *crowdaction) GetAll() ([]m.CrowdactionData, error) { + crowdactions := []m.CrowdactionData{} // crowdactions array + var filterCond = expression.Name(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) + + item, err := s.dbClient.Scan(constants.TableName, filterCond) + if item == nil || err != nil { + return nil, err + } + + for _, itemIterator := range item { + var crowdaction m.CrowdactionData + err := dynamodbattribute.UnmarshalMap(itemIterator, &crowdaction) + + if err == nil { + crowdactions = append(crowdactions, crowdaction) + } + } + + if len(item) != len(crowdactions) { + err = fmt.Errorf("error unmarshallaing %d items", len(item)-len(crowdactions)) + } + + return crowdactions, err +} + func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) { crowdactions := []m.CrowdactionData{} var filterCond expression.ConditionBuilder @@ -55,15 +97,11 @@ func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([ switch status { case "joinable": filterCond = expression.Name(KeyDateJoinBefore).GreaterThan(expression.Value(utils.GetDateStringNow())) - fmt.Println("GetByStatus: joinable", filterCond) case "active": filterCond = expression.Name(KeyDateStart).LessThanEqual(expression.Value(utils.GetDateStringNow())) - fmt.Println("GetByStatus: active", filterCond) case "ended": filterCond = expression.Name(KeyDateEnd).LessThanEqual(expression.Value(utils.GetDateStringNow())) - fmt.Println("GetByStatus: ended", filterCond) default: - fmt.Println("None of the edge cases matched") } items, err := s.dbClient.Query(constants.TableName, filterCond, startFrom) @@ -72,9 +110,9 @@ func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([ return nil, err } - for _, foo := range items { + for _, itemIterator := range items { var crowdaction m.CrowdactionData - err := dynamodbattribute.UnmarshalMap(foo, &crowdaction) + err := dynamodbattribute.UnmarshalMap(itemIterator, &crowdaction) if err == nil { crowdactions = append(crowdactions, crowdaction) @@ -87,3 +125,22 @@ func (s *crowdaction) GetByStatus(status string, startFrom *utils.PrimaryKey) ([ return crowdactions, err } + +func (s *crowdaction) Register(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) { + var response m.CrowdactionData + generatedID := RandomIDPrefix(8) + pk := utils.PKCrowdaction + sk := payload.Category + "#" + payload.Subcategory + "#" + generatedID + payload.CrowdactionID = sk + response = payload + // should modify the payload here to include the crowdcationID + // fmt.Println("payload", payload) + fmt.Println("9. pkg/respository/aws/crowdactionManager.go", payload) + + err := s.dbClient.PutDBItem(constants.TableName, pk, sk, payload) + + if err != nil { + return &response, nil + } + return &response, err +} diff --git a/pkg/repository/aws/dynamo.go b/pkg/repository/aws/dynamo.go index 0698ba8..628b591 100644 --- a/pkg/repository/aws/dynamo.go +++ b/pkg/repository/aws/dynamo.go @@ -92,6 +92,20 @@ func (s *Dynamo) GetDBItem(tableName string, pk string, sk string) (map[string]* return result.Item, nil } +func (s *Dynamo) Scan(tableName string, filterCond expression.ConditionBuilder) ([]map[string]*dynamodb.AttributeValue, error) { + expr, _ := expression.NewBuilder().WithFilter(filterCond).Build() + + result, err := s.dbClient.Scan(&dynamodb.ScanInput{ + ExpressionAttributeNames: expr.Names(), + ExpressionAttributeValues: expr.Values(), + FilterExpression: expr.Filter(), + ProjectionExpression: expr.Projection(), + TableName: aws.String(tableName), + }) + + return result.Items, err +} + func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, startFrom *utils.PrimaryKey) ([]map[string]*dynamodb.AttributeValue, error) { keyCond := expression.Key(utils.PartitionKey).Equal(expression.Value(utils.PKCrowdaction)) expr, _ := expression.NewBuilder().WithKeyCondition(keyCond).WithFilter(filterCond).Build() @@ -102,6 +116,9 @@ func (s *Dynamo) Query(tableName string, filterCond expression.ConditionBuilder, exclusiveStartKey = *startFrom } + // here filter does have a reference + fmt.Println("Query expr", expr.Names(), expr.Filter(), expr.Values()) + result, err := s.dbClient.Query(&dynamodb.QueryInput{ Limit: aws.Int64(utils.CrowdactionsPageLength), ExclusiveStartKey: exclusiveStartKey, diff --git a/pkg/repository/aws/uploadProfilePictureManager.go b/pkg/repository/aws/uploadProfilePictureManager.go new file mode 100644 index 0000000..11616bd --- /dev/null +++ b/pkg/repository/aws/uploadProfilePictureManager.go @@ -0,0 +1,38 @@ +package aws + +import ( + "context" + "os" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" +) + +type ProfilePicture struct { + Client *s3.S3 +} + +func NewProfilePicture(sess *session.Session) *ProfilePicture { + return &ProfilePicture{Client: s3.New(sess)} +} + +func (p *ProfilePicture) GetUploadUrl(ctx context.Context, ext string, userID string) (string, error) { + var ( + bucket = os.Getenv("BUCKET") + filekey = userID + "." + ext + ) + + reqs, _ := p.Client.PutObjectRequest(&s3.PutObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(filekey), + }) + + str, err := reqs.Presign(15 * time.Minute) + + if err != nil { + return "", err + } + return str, nil +} diff --git a/template.yaml b/template.yaml index 6f27144..9b76c4c 100644 --- a/template.yaml +++ b/template.yaml @@ -195,7 +195,7 @@ Resources: UploadProfilePictureFunction: Type: AWS::Serverless::Function Properties: - CodeUri: upload-profile-picture/ + CodeUri: pkg/handler/aws/uploadProfilePicture Handler: upload-profile-picture Runtime: go1.x Environment: @@ -281,6 +281,15 @@ Resources: Handler: crowdaction Runtime: go1.x Events: + # TODO feature wip (cms) + CreateCrowdaction: + Type: HttpApi + Properties: + Path: /cms/crowdactions + Method: post + ApiId: !Ref HttpApi + Auth: + Authorizer: "NONE" FetchCrowdaction: Type: HttpApi Properties: From ffa947c3f101186087664f02cb7161a83825b03d Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 11 Jun 2022 19:18:22 +0200 Subject: [PATCH 41/67] cleaning up the aws crowdaction repository --- pkg/repository/aws/crowdactionManager.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/repository/aws/crowdactionManager.go b/pkg/repository/aws/crowdactionManager.go index 3f69fc5..27ea510 100644 --- a/pkg/repository/aws/crowdactionManager.go +++ b/pkg/repository/aws/crowdactionManager.go @@ -18,7 +18,6 @@ type Crowdaction interface { GetById(pk string, sk string) (*m.CrowdactionData, error) GetByStatus(status string, startFrom *utils.PrimaryKey) ([]m.CrowdactionData, error) Register(ctx context.Context, payload m.CrowdactionData) (*m.CrowdactionData, error) - // Register(ctx context.Context, payload m.CrowdactionData) error } const ( @@ -133,9 +132,6 @@ func (s *crowdaction) Register(ctx context.Context, payload m.CrowdactionData) ( sk := payload.Category + "#" + payload.Subcategory + "#" + generatedID payload.CrowdactionID = sk response = payload - // should modify the payload here to include the crowdcationID - // fmt.Println("payload", payload) - fmt.Println("9. pkg/respository/aws/crowdactionManager.go", payload) err := s.dbClient.PutDBItem(constants.TableName, pk, sk, payload) From 50a9d433a7362371c07ea3179b564bb928a6f0fb Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 11 Jun 2022 19:22:32 +0200 Subject: [PATCH 42/67] functions to handle the badge logic for now these functions are written in python, but it would be great to move it to go at some point --- badges/eventbus.py | 107 +++++++++++++++++++++++++++++++++++++++++++++ badges/trigger.py | 84 +++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 badges/eventbus.py create mode 100644 badges/trigger.py diff --git a/badges/eventbus.py b/badges/eventbus.py new file mode 100644 index 0000000..d062a53 --- /dev/null +++ b/badges/eventbus.py @@ -0,0 +1,107 @@ +# This function should be responsible for point system calculation +# as well as the event rule deletion from the bus once the crowdaction +# terminates + +import json +import logging +import boto3 + +e_client = boto3.client('events') +l_client = boto3.client('lambda') +d_client = boto3.client('dynamodb') + + +def compute_badge_award(points, reward_list): + print('point system: ', points, reward_list) + """ + There is an assumption about the order + of the reward_list. This is taken into + account a descending order + """ + if points >= int(reward_list[3]): + return "Diamond" + elif points >= int(reward_list[2]): + return "Golden" + elif points >= int(reward_list[1]): + return "Silver" + elif points >= int(reward_list[0]): + return "Bronze" + else: + return "No reward" + + +def ddb_query(table, usr_id, reward, crowdaction_id): + d_client.update_item( + TableName=table, + Key={ + 'userid': { + 'S': usr_id, + } + }, + AttributeUpdates={ + 'reward': { + 'Value': { + 'L': [ + { + "M": { + "award": { + "S": reward + }, + "crowdactionID": { + "S": crowdaction_id + } + } + }, + ], + }, + 'Action': 'ADD' + } + }, + ) + + +def lambda_handler(event, context): + # static + # this table should be obtained from + # specific crowdaction, because it'll break + # :( + # map the tree to a dictionary + + prt_commit = { + "no-beef": 5, + "pescatarian": 10, + "no-dairy": 20, + "vegetarian": 30, + "vegan": 70 + } + badge_reward_list = [] + + target_name = 'lambda_cron_test_end_date' + single_table = 'collaction-dev-edreinoso-SingleTable-BAXICTFSQ4WV' + profile_table = 'collaction-dev-edreinoso-ProfileTable-XQEJJNBK6UUY' + # crowdaction_id = event['resources'][0].split('/')[1] + crowdaction_id = 'sustainability#food#185f66fd' + participant_sk = "prt#act#" + crowdaction_id + print('Lambda Crontab!', event['resources'] + [0].split('/')[1].replace('_', '#')) + + # POINT CALCULATION LOGIC + + # 2. fetch the badge scale for crowdaction ✅ + badge_scale = d_client.get_item( + TableName=single_table, + Key={ + 'pk': {'S': 'act'}, + 'sk': {'S': crowdaction_id} + } + ) + # print(badge_scale) + print(badge_scale['Item']['commitment_options']) + # for reward in badge_scale['Item']['badges']['L']: + # badge_reward_list.append(reward['N']) + # print(badge_reward_list) + + return { + 'statusCode': 200, + 'body': json.dumps('Crowdaction Ended!') + } diff --git a/badges/trigger.py b/badges/trigger.py new file mode 100644 index 0000000..537d251 --- /dev/null +++ b/badges/trigger.py @@ -0,0 +1,84 @@ +""" + This function should be responsible for keeping track of the end date + of the crowdaction, to record it in the event bus for later point + system calculation +""" + +from datetime import datetime +import logging +import boto3 +import json +import random +import string + +e_client = boto3.client('events') +l_client = boto3.client('lambda') + + +def lambda_handler(event, context): + if(event['Records'][0]['eventName'] == 'INSERT'): + record = event['Records'][0]['dynamodb']['NewImage'] + + # TODO: test this! + # checking for records that are only for crowdactions + if (record['pk']['S'] != "act"): + return { + 'statusCode': 200, + 'body': json.dumps('Event is not crowdaction') + } + + target_arn = 'arn:aws:lambda:eu-central-1:156764677614:function:lambda_cron_test_end_date' + target_name = 'lambda_cron_test_end_date' + action = 'lambda:InvokeFunction' + + title = record['title']['S'] + description = record['description']['S'] + date_end = record['date_end']['S'] + crowdaction_id = record['sk']['S'].replace('#', '_') + # may have to handle date exception + date_end_expr = datetime_to_cron( + datetime.strptime(date_end, "%Y-%m-%d %H:%M:%S")) + + # PUT TARGET + e_client.put_rule( + Name=crowdaction_id, + ScheduleExpression=date_end_expr, + State='ENABLED', + Description='event rule for ' + crowdaction_id, + ) + + # PUT TARGET + e_client.put_targets( + Rule=crowdaction_id, + Targets=[ + { + 'Id': crowdaction_id, + 'Arn': target_arn, + }, + ] + ) + + # ADD PERMISSIONS + l_client.add_permission( + FunctionName=target_name, + StatementId=crowdaction_id, + Action=action, + Principal='events.amazonaws.com', + SourceArn='arn:aws:events:eu-central-1:156764677614:rule/'+crowdaction_id, + ) + + print('rule has been placed on the bus') + + return { + 'statusCode': 200, + 'body': json.dumps('End day has been scheduled!') + } + + +""" + Function that would convert datetime into cronjobs +""" + + +def datetime_to_cron(dt): + return f"cron({dt.minute} {dt.hour} {dt.day} {dt.month} ? {dt.year})" From 64753c46302ef591ff469cca7f324f3258828cfd Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 11 Jun 2022 19:23:04 +0200 Subject: [PATCH 43/67] test script in python for the badge logic --- scripts/badges/api.py | 235 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 scripts/badges/api.py diff --git a/scripts/badges/api.py b/scripts/badges/api.py new file mode 100644 index 0000000..b614b6d --- /dev/null +++ b/scripts/badges/api.py @@ -0,0 +1,235 @@ +""" + Script for calling API gateway endpoints + if the API is not available, then try to use + boto3 to put records in DynamoDB +""" +from datetime import datetime +from datetime import timedelta +import json +import string +import random +import boto3 +import requests + + +l_client = boto3.client('lambda') + + +def id_generator(size=6, chars=string.ascii_letters + string.digits): + return ''.join(random.choice(chars) for _ in range(size)) + + +""" + CREATE USER + put user in profile dynamodb + randomID for the user + if the API is not working, + the work around is to use boto3 + or event the other work would be + to use an event directly + the idea is to create couple of users, + save them in a list to use later in the + participation portion of the script +""" + +""" + for loop + post - multiple users + save them into a list + along with their commitment +""" +commitment_arr = [ + "no-diary", + "no-cheese", + "no-beef", + "pescatarian", + "vegetarian", + "vegan" +] + +randomNum = random.randrange(4) # this should be inside for loop +usr_list = [ + {"id": usr_id, "commitment": commitment_arr[randomNum]} +] + +# randomly create a user_id +usr_id = id_generator(28) +usr_payload = { + "body": "{\"displayname\": \"Timothy\", \"city\": \"New York\", \"country\": \"USA\", \"bio\": \"Hi, I'm Timothy\"}", + "pathParameters": { + "userID": usr_id + }, + "requestContext": { + "authorizer": { + "jwt": { + "claims": { + "name": "Timothy", + "user_id": usr_id, + "sub": usr_id, + "phone_number": "+31612345678" + } + } + }, + "http": { + "method": "POST" + } + } +} + +# uri = 'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/cms/crowdactions' +# user = requests.post(uri, json=usr_payload) +# print(user.json()) +res = l_client.invoke( + FunctionName='collaction-dev-edreinoso-ProfileCRUDFunction-gLFLlRBye4eA', + InvocationType='RequestResponse', + Payload=bytes(json.dumps(usr_payload), encoding='utf8'), +) +print(res) + +""" + CREATE CROWDACTION +""" +current_time = datetime.now() + +gmt_time = datetime.now() - timedelta(hours=2) # converting time to GMT +crowdacticon_date_end = gmt_time + timedelta(minutes=7) +crowdacticon_date_limit = gmt_time + timedelta(minutes=4) +# datetime.now().strftime("%Y-%m-%d") +crowdaction_start_time = gmt_time.replace(microsecond=0) +crowdaction_expiry_time = crowdacticon_date_end.replace(microsecond=0) +crowdaction_join_limit = crowdacticon_date_limit.replace(microsecond=0) + +category = id_generator(8) +subcategory = id_generator(8) + +cwr_payload = { + "title": "querico", + "description": "test1", + "category": category, + "subcategory": subcategory, + "location": "test1", + "date_end": str(crowdaction_expiry_time), + "date_start": str(crowdaction_start_time), + "date_limit_join": "2022-05-24", + # "date_limit_join": str(crowdaction_join_limit), + "password_join": "", + "images": { + "card": "hello", + "banner": "world" + }, + "badges": [20, 40, 60, 80], + "participation_count": 0, + "top_participants": [], + "commitment_options": [ + { + "description": "(in case you dont want to commit to 7/7 days a week)", + "id": "working-days-only", + "label": "5/7 days a week" + }, + { + "description": "", + "id": "vegan", + "label": "Vegan", + "requires": [ + { + "description": "", + "id": "vegetarian", + "label": "Vegetarian", + "requires": [ + { + "description": "", + "id": "pescatarian", + "label": "Pescatarian", + "requires": [ + { + "description": "", + "id": "no-beef", + "label": "No Beef" + } + ] + } + ] + }, + { + "description": "", + "id": "no-dairy", + "label": "No Dairy", + "requires": [ + { + "description": "", + "id": "no-cheese", + "label": "No Cheese" + } + ] + } + ] + } + ], +} + +uri = 'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/cms/crowdactions' + +# # print(cwr_payload) + +# # # TODO: return the crowdaction object that was created +res = requests.post(uri, json=cwr_payload) +crowdaction = res.json() +cid = crowdaction['data']['crowdactionID'] +print(cid) + +""" + # CREATE PARTICIPATION + take the newly created user ID + take the newly created crowdaction ID + I would like to be returing the crowdaction itself + not necessary if I end up using the + category and + subcategory + variables + this could be a for loop that iterates + through a stack of users (with their ID) +""" + +""" + for n in list of users + from list + grab the id + grab the commimtment +""" + +prt_payload = { + # it would be nice that the commitment is randomly generated based on certain + # options + "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"no-beef\"]}", + "pathParameters": { + "crowdactionID": cid + }, + "requestContext": { + "authorizer": { + "jwt": { + "claims": { + "name": "Hello World", + "user_id": usr_id, + "sub": usr_id, + "phone_number": "+31612345678" + } + } + }, + "http": { + "method": "POST" + } + } +} + +# uri = f'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/crowdactions/{crowdactionId}/participation' +# # for n in range(0,10): +# participation = requests.post(uri, json=prt_payload) +# print(participation.json()) + +res = l_client.invoke( + FunctionName='collaction-dev-edreinoso-ParticipationFunction-zc9MRMJVkIjO', + InvocationType='RequestResponse', + Payload=bytes(json.dumps(prt_payload), encoding='utf8'), +) + +print(res) From cca61ca992e7d3267fdff469452ceb9fc5972ed4 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 11 Jun 2022 19:27:38 +0200 Subject: [PATCH 44/67] organisation for retaking the badge logic laid out the steps that needed to be done in order to accomplish the task --- badges/eventbus.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index d062a53..f4fcff4 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -61,12 +61,6 @@ def ddb_query(table, usr_id, reward, crowdaction_id): def lambda_handler(event, context): - # static - # this table should be obtained from - # specific crowdaction, because it'll break - # :( - # map the tree to a dictionary - prt_commit = { "no-beef": 5, "pescatarian": 10, @@ -101,6 +95,11 @@ def lambda_handler(event, context): # badge_reward_list.append(reward['N']) # print(badge_reward_list) + # 3. restructure the tree to a dictionary + # 4. go through all participants + # 5. validate their commitment level + # 6. award badge + return { 'statusCode': 200, 'body': json.dumps('Crowdaction Ended!') From 23432b94ccd7d9fd8bcd06f2d6b5fe31803ee680 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Mon, 13 Jun 2022 19:00:21 +0200 Subject: [PATCH 45/67] initial tree recursion recursing through the tree to get key and value (ideally) of each commitment option from the crowdaction --- badges/eventbus.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index f4fcff4..0c756ce 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -60,6 +60,13 @@ def ddb_query(table, usr_id, reward, crowdaction_id): ) +def tree_recursion(commit_list): + for i in range(0, len(commit_list)): + print(commit_list[i]['M']) + if 'requires' in commit_list[i]['M']: + tree_recursion(commit_list[i]['M']['requires']['L']) + + def lambda_handler(event, context): prt_commit = { "no-beef": 5, @@ -90,12 +97,25 @@ def lambda_handler(event, context): } ) # print(badge_scale) - print(badge_scale['Item']['commitment_options']) + print(badge_scale['Item']['commitment_options']['L']) + tree = badge_scale['Item']['commitment_options']['L'] + commit_dict = {} # for reward in badge_scale['Item']['badges']['L']: # badge_reward_list.append(reward['N']) # print(badge_reward_list) - # 3. restructure the tree to a dictionary + # 3. restructure the tree to a dictionary ⏰ + for n in range(0, len(tree)): + t = tree[n]['M'] + commit_key = t['id']['S'] # should be the key + commit_label = t['label']['S'] # placeholder + # commit_val = t['point']['S'] # should be the numeric value, future + print(tree[n]['M']) + commit_dict[commit_key] = commit_label + if 'requires' in t: + # call recursion + tree_recursion(t['requires']['L']) + # 4. go through all participants # 5. validate their commitment level # 6. award badge From d40a02ad8554e445ee49998248e84a60d70e60c9 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 14 Jun 2022 10:35:14 +0200 Subject: [PATCH 46/67] optimised the tree recursion --- badges/eventbus.py | 51 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 0c756ce..d65d33e 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -10,6 +10,8 @@ l_client = boto3.client('lambda') d_client = boto3.client('dynamodb') +commit_dict = {} + def compute_badge_award(points, reward_list): print('point system: ', points, reward_list) @@ -60,11 +62,17 @@ def ddb_query(table, usr_id, reward, crowdaction_id): ) -def tree_recursion(commit_list): - for i in range(0, len(commit_list)): - print(commit_list[i]['M']) - if 'requires' in commit_list[i]['M']: - tree_recursion(commit_list[i]['M']['requires']['L']) +def tree_recursion(tree): + for i in range(0, len(tree)): + t = tree[i]['M'] + # print(t) + commit_key = t['id']['S'] + commit_label = t['label']['S'] + commit_dict[commit_key] = commit_label + # print(commit_key, commit_label) + if 'requires' in t: + # print('\t\trequire is inside of t') + tree_recursion(t['requires']['L']) def lambda_handler(event, context): @@ -86,9 +94,11 @@ def lambda_handler(event, context): print('Lambda Crontab!', event['resources'] [0].split('/')[1].replace('_', '#')) - # POINT CALCULATION LOGIC + """ + POINT CALCULATION LOGIC + """ - # 2. fetch the badge scale for crowdaction ✅ + # 1. fetch the badge scale for crowdaction ✅ badge_scale = d_client.get_item( TableName=single_table, Key={ @@ -96,29 +106,20 @@ def lambda_handler(event, context): 'sk': {'S': crowdaction_id} } ) - # print(badge_scale) - print(badge_scale['Item']['commitment_options']['L']) tree = badge_scale['Item']['commitment_options']['L'] - commit_dict = {} + print(tree) + # commit_dict = {} # this is global for now, but could be changed # for reward in badge_scale['Item']['badges']['L']: # badge_reward_list.append(reward['N']) # print(badge_reward_list) - # 3. restructure the tree to a dictionary ⏰ - for n in range(0, len(tree)): - t = tree[n]['M'] - commit_key = t['id']['S'] # should be the key - commit_label = t['label']['S'] # placeholder - # commit_val = t['point']['S'] # should be the numeric value, future - print(tree[n]['M']) - commit_dict[commit_key] = commit_label - if 'requires' in t: - # call recursion - tree_recursion(t['requires']['L']) - - # 4. go through all participants - # 5. validate their commitment level - # 6. award badge + # 2. restructure the tree to a dictionary ⏰ + tree_recursion(tree) + print(commit_dict) # verifying the dictionary convertion + + # 3. go through all participants + # 4. validate their commitment level + # 5. award badge return { 'statusCode': 200, From a162571db5329de39663ab2347a6632cdb1e7283 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 14 Jun 2022 11:01:59 +0200 Subject: [PATCH 47/67] included the points for commitments --- badges/eventbus.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index d65d33e..db8cb75 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -67,22 +67,15 @@ def tree_recursion(tree): t = tree[i]['M'] # print(t) commit_key = t['id']['S'] - commit_label = t['label']['S'] - commit_dict[commit_key] = commit_label - # print(commit_key, commit_label) + commit_points = t['points']['N'] + commit_dict[commit_key] = commit_points + # print(commit_key, commit_points) if 'requires' in t: # print('\t\trequire is inside of t') tree_recursion(t['requires']['L']) def lambda_handler(event, context): - prt_commit = { - "no-beef": 5, - "pescatarian": 10, - "no-dairy": 20, - "vegetarian": 30, - "vegan": 70 - } badge_reward_list = [] target_name = 'lambda_cron_test_end_date' From 1f4a2df6618244b49a1a23afdbabcfc3ffdd771f Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 14 Jun 2022 18:20:34 +0200 Subject: [PATCH 48/67] querying table for participants --- badges/eventbus.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index db8cb75..10e3d03 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -10,7 +10,7 @@ l_client = boto3.client('lambda') d_client = boto3.client('dynamodb') -commit_dict = {} +commit_dict = {} # this may be global for now def compute_badge_award(points, reward_list): @@ -101,17 +101,28 @@ def lambda_handler(event, context): ) tree = badge_scale['Item']['commitment_options']['L'] print(tree) - # commit_dict = {} # this is global for now, but could be changed # for reward in badge_scale['Item']['badges']['L']: # badge_reward_list.append(reward['N']) # print(badge_reward_list) - # 2. restructure the tree to a dictionary ⏰ + # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) print(commit_dict) # verifying the dictionary convertion - # 3. go through all participants + # 3. go through all participants ✅ + participant_list = d_client.query( + TableName=single_table, + IndexName='invertedIndex', + KeyConditionExpression="sk = :sk", + ExpressionAttributeValues={ + ':sk': {'S': f'prt#act#{crowdaction_id}'} + }, + ) + + print(participant_list['Items']) + # 4. validate their commitment level + # 5. award badge return { From 979ddb43ab64a76b2bf3a8d0b3f75653709f828a Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 14 Jun 2022 18:32:02 +0200 Subject: [PATCH 49/67] initial participation logic comparison --- badges/eventbus.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 10e3d03..7b9a9ec 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -100,10 +100,9 @@ def lambda_handler(event, context): } ) tree = badge_scale['Item']['commitment_options']['L'] - print(tree) - # for reward in badge_scale['Item']['badges']['L']: - # badge_reward_list.append(reward['N']) - # print(badge_reward_list) + for reward in badge_scale['Item']['badges']['L']: + badge_reward_list.append(reward['N']) + print(badge_reward_list) # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) @@ -119,9 +118,13 @@ def lambda_handler(event, context): }, ) - print(participant_list['Items']) - - # 4. validate their commitment level + # 4. validate their commitment level ⏰ + for i in range(0, len(participant_list['Items'])): + prt_details = participant_list['Items'][i] + prt_lvl = prt_details['commitments']['L'][0]['S'] + print(prt_lvl) + if prt_lvl in commit_dict: + compute_badge_award(commit_dict[prt_lvl], reward_list) # 5. award badge From f1bb459f31c977590d4e71b8985d7e49f944b9cb Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 15 Jun 2022 12:21:26 +0200 Subject: [PATCH 50/67] badge point user mapping --- badges/eventbus.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 7b9a9ec..5484867 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -14,19 +14,19 @@ def compute_badge_award(points, reward_list): - print('point system: ', points, reward_list) + print('point system: ', type(points), reward_list) """ There is an assumption about the order of the reward_list. This is taken into account a descending order """ - if points >= int(reward_list[3]): + if int(points) >= int(reward_list[3]): return "Diamond" - elif points >= int(reward_list[2]): + elif int(points) >= int(reward_list[2]): return "Golden" - elif points >= int(reward_list[1]): + elif int(points) >= int(reward_list[1]): return "Silver" - elif points >= int(reward_list[0]): + elif int(points) >= int(reward_list[0]): return "Bronze" else: return "No reward" @@ -65,13 +65,10 @@ def ddb_query(table, usr_id, reward, crowdaction_id): def tree_recursion(tree): for i in range(0, len(tree)): t = tree[i]['M'] - # print(t) commit_key = t['id']['S'] commit_points = t['points']['N'] commit_dict[commit_key] = commit_points - # print(commit_key, commit_points) if 'requires' in t: - # print('\t\trequire is inside of t') tree_recursion(t['requires']['L']) @@ -118,14 +115,23 @@ def lambda_handler(event, context): }, ) - # 4. validate their commitment level ⏰ + # 4. validate their commitment level ✅ + user_prt_list = [] # list required to store individual participations for i in range(0, len(participant_list['Items'])): prt_details = participant_list['Items'][i] + usr_id = prt_details['userID']['S'] prt_lvl = prt_details['commitments']['L'][0]['S'] - print(prt_lvl) + usr_obj = { + "userid": usr_id, + "prt": prt_lvl, + "points": commit_dict[prt_lvl] + } if prt_lvl in commit_dict: - compute_badge_award(commit_dict[prt_lvl], reward_list) + usr_obj['badge'] = compute_badge_award( + commit_dict[prt_lvl], badge_reward_list) + user_prt_list.append(usr_obj) + print(user_prt_list) # 5. award badge return { From 9b444011aa02f2bcdca0277aa4b45258c87af333 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 15 Jun 2022 12:32:13 +0200 Subject: [PATCH 51/67] badge point ddb table update --- badges/eventbus.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 5484867..bd65b9c 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -14,7 +14,6 @@ def compute_badge_award(points, reward_list): - print('point system: ', type(points), reward_list) """ There is an assumption about the order of the reward_list. This is taken into @@ -32,7 +31,15 @@ def compute_badge_award(points, reward_list): return "No reward" -def ddb_query(table, usr_id, reward, crowdaction_id): +def ddb_get_item(table, crowdaction_id): + pass + + +def ddb_query(table, crowdaction_id): + pass + + +def ddb_update(table, usr_id, reward, crowdaction_id): d_client.update_item( TableName=table, Key={ @@ -56,7 +63,7 @@ def ddb_query(table, usr_id, reward, crowdaction_id): }, ], }, - 'Action': 'ADD' + 'Action': 'ADD' # this operations still pending } }, ) @@ -131,8 +138,11 @@ def lambda_handler(event, context): commit_dict[prt_lvl], badge_reward_list) user_prt_list.append(usr_obj) - print(user_prt_list) - # 5. award badge + # print(user_prt_list) + + # 5. award badge ⏰ + for usr in user_prt_list: + ddb_update(profile_table, usr['userid'], usr['badge'], crowdaction_id) return { 'statusCode': 200, From 85513811fad6faa03f6b413180820d547e41b0ab Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 15 Jun 2022 12:55:10 +0200 Subject: [PATCH 52/67] separation of concerns in ddb operations --- badges/dynamodb.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++ badges/eventbus.py | 76 ++++++++------------------------------------- 2 files changed, 90 insertions(+), 63 deletions(-) create mode 100644 badges/dynamodb.py diff --git a/badges/dynamodb.py b/badges/dynamodb.py new file mode 100644 index 0000000..18d6fee --- /dev/null +++ b/badges/dynamodb.py @@ -0,0 +1,77 @@ +import boto3 +d_client = boto3.client('dynamodb') + + +class ddb_ops(): + """ + Get Item + """ + + def get_item(self, table, crowdaction_id): + self.table = table + self.crowdaction_id = crowdaction_id + + res = d_client.get_item( + TableName=table, + Key={ + 'pk': {'S': 'act'}, + 'sk': {'S': crowdaction_id} + } + ) + return res + + """ + Query Items + """ + + def query(self, table, crowdaction_id): + self.table = table + self.crowdaction_id = crowdaction_id + + res = d_client.query( + TableName=table, + IndexName='invertedIndex', + KeyConditionExpression="sk = :sk", + ExpressionAttributeValues={ + ':sk': {'S': f'prt#act#{crowdaction_id}'} + }, + ) + return res + """ + + Update Items + """ + + def update(self, table, usr_id, reward, crowdaction_id): + self.table = table + self.usr_id = usr_id + self.reward = reward + self.crowdaction_id = crowdaction_id + + d_client.update_item( + TableName=table, + Key={ + 'userid': { + 'S': usr_id, + } + }, + AttributeUpdates={ + 'reward': { + 'Value': { + 'L': [ + { + "M": { + "award": { + "S": reward + }, + "crowdactionID": { + "S": crowdaction_id + } + } + }, + ], + }, + 'Action': 'ADD' # this operations still pending + } + }, + ) diff --git a/badges/eventbus.py b/badges/eventbus.py index bd65b9c..14dde81 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -5,10 +5,12 @@ import json import logging import boto3 - +import os +from dynamodb import * e_client = boto3.client('events') l_client = boto3.client('lambda') -d_client = boto3.client('dynamodb') + +ddb = ddb_ops() commit_dict = {} # this may be global for now @@ -31,44 +33,6 @@ def compute_badge_award(points, reward_list): return "No reward" -def ddb_get_item(table, crowdaction_id): - pass - - -def ddb_query(table, crowdaction_id): - pass - - -def ddb_update(table, usr_id, reward, crowdaction_id): - d_client.update_item( - TableName=table, - Key={ - 'userid': { - 'S': usr_id, - } - }, - AttributeUpdates={ - 'reward': { - 'Value': { - 'L': [ - { - "M": { - "award": { - "S": reward - }, - "crowdactionID": { - "S": crowdaction_id - } - } - }, - ], - }, - 'Action': 'ADD' # this operations still pending - } - }, - ) - - def tree_recursion(tree): for i in range(0, len(tree)): t = tree[i]['M'] @@ -96,33 +60,21 @@ def lambda_handler(event, context): """ # 1. fetch the badge scale for crowdaction ✅ - badge_scale = d_client.get_item( - TableName=single_table, - Key={ - 'pk': {'S': 'act'}, - 'sk': {'S': crowdaction_id} - } - ) + badge_scale = ddb.get_item(single_table, crowdaction_id) + tree = badge_scale['Item']['commitment_options']['L'] for reward in badge_scale['Item']['badges']['L']: badge_reward_list.append(reward['N']) - print(badge_reward_list) + # print(badge_reward_list) # verfying the badge reward list # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) - print(commit_dict) # verifying the dictionary convertion + # print(commit_dict) # verifying the dictionary convertion # 3. go through all participants ✅ - participant_list = d_client.query( - TableName=single_table, - IndexName='invertedIndex', - KeyConditionExpression="sk = :sk", - ExpressionAttributeValues={ - ':sk': {'S': f'prt#act#{crowdaction_id}'} - }, - ) - - # 4. validate their commitment level ✅ + participant_list = ddb.query(single_table, crowdaction_id) + + # 4. map user commitment level ✅ user_prt_list = [] # list required to store individual participations for i in range(0, len(participant_list['Items'])): prt_details = participant_list['Items'][i] @@ -138,11 +90,9 @@ def lambda_handler(event, context): commit_dict[prt_lvl], badge_reward_list) user_prt_list.append(usr_obj) - # print(user_prt_list) - - # 5. award badge ⏰ + # 5. award badge ✅ for usr in user_prt_list: - ddb_update(profile_table, usr['userid'], usr['badge'], crowdaction_id) + ddb.update(profile_table, usr['userid'], usr['badge'], crowdaction_id) return { 'statusCode': 200, From b77847f2e1eff5ba861ae4c0a4895bb9727cb97a Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 16 Jun 2022 11:18:50 +0200 Subject: [PATCH 53/67] minor changes to the badge test script parameters and some comments were made --- scripts/badges/api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index b614b6d..db9ac54 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -48,9 +48,9 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): ] randomNum = random.randrange(4) # this should be inside for loop -usr_list = [ - {"id": usr_id, "commitment": commitment_arr[randomNum]} -] +# usr_list = [ +# {"id": usr_id, "commitment": commitment_arr[randomNum]} +# ] # randomly create a user_id usr_id = id_generator(28) @@ -110,7 +110,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): "location": "test1", "date_end": str(crowdaction_expiry_time), "date_start": str(crowdaction_start_time), - "date_limit_join": "2022-05-24", + "date_limit_join": "2022-06-19", # "date_limit_join": str(crowdaction_join_limit), "password_join": "", "images": { @@ -171,7 +171,6 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): # # print(cwr_payload) -# # # TODO: return the crowdaction object that was created res = requests.post(uri, json=cwr_payload) crowdaction = res.json() cid = crowdaction['data']['crowdactionID'] @@ -190,6 +189,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): through a stack of users (with their ID) """ +# TODO: complete this loop """ for n in list of users from list @@ -200,7 +200,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): prt_payload = { # it would be nice that the commitment is randomly generated based on certain # options - "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"no-beef\"]}", + "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"vegan\"]}", "pathParameters": { "crowdactionID": cid }, From 6d33f4809571938c4876efa3e011af4caa13fc2c Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 16 Jun 2022 17:01:43 +0200 Subject: [PATCH 54/67] minor change for point calculation system --- badges/eventbus.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 14dde81..e210e31 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -51,7 +51,7 @@ def lambda_handler(event, context): profile_table = 'collaction-dev-edreinoso-ProfileTable-XQEJJNBK6UUY' # crowdaction_id = event['resources'][0].split('/')[1] crowdaction_id = 'sustainability#food#185f66fd' - participant_sk = "prt#act#" + crowdaction_id + # participant_sk = "prt#act#" + crowdaction_id print('Lambda Crontab!', event['resources'] [0].split('/')[1].replace('_', '#')) @@ -65,31 +65,37 @@ def lambda_handler(event, context): tree = badge_scale['Item']['commitment_options']['L'] for reward in badge_scale['Item']['badges']['L']: badge_reward_list.append(reward['N']) - # print(badge_reward_list) # verfying the badge reward list + # print(badge_reward_list) # verfying the badge reward list # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) - # print(commit_dict) # verifying the dictionary convertion + # print(commit_dict) # verifying the dictionary convertion # 3. go through all participants ✅ participant_list = ddb.query(single_table, crowdaction_id) + # print(participant_list) # 4. map user commitment level ✅ user_prt_list = [] # list required to store individual participations for i in range(0, len(participant_list['Items'])): prt_details = participant_list['Items'][i] usr_id = prt_details['userID']['S'] - prt_lvl = prt_details['commitments']['L'][0]['S'] + prt_lvl = prt_details['commitments']['L'] + usr_prt_counter = 0 + for n in range(0, len(prt_lvl)): + usr_prt_counter += int(commit_dict[prt_lvl[n]['S']]) usr_obj = { "userid": usr_id, "prt": prt_lvl, - "points": commit_dict[prt_lvl] + "points": usr_prt_counter } - if prt_lvl in commit_dict: - usr_obj['badge'] = compute_badge_award( - commit_dict[prt_lvl], badge_reward_list) + # if prt_lvl in commit_dict: # would I be assuming that a user would always have a participation + usr_obj['badge'] = compute_badge_award( + usr_prt_counter, badge_reward_list) user_prt_list.append(usr_obj) + print(user_prt_list) + # 5. award badge ✅ for usr in user_prt_list: ddb.update(profile_table, usr['userid'], usr['badge'], crowdaction_id) From 70f9937fbb47087750c83caa652efc73d675ebdb Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 16 Jun 2022 17:02:51 +0200 Subject: [PATCH 55/67] minor changes to test badge award included proper participation, smaller time for expiration and more accurate point rewarding --- scripts/badges/api.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index db9ac54..4f55268 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -92,7 +92,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): current_time = datetime.now() gmt_time = datetime.now() - timedelta(hours=2) # converting time to GMT -crowdacticon_date_end = gmt_time + timedelta(minutes=7) +crowdacticon_date_end = gmt_time + timedelta(minutes=3) crowdacticon_date_limit = gmt_time + timedelta(minutes=4) # datetime.now().strftime("%Y-%m-%d") crowdaction_start_time = gmt_time.replace(microsecond=0) @@ -124,27 +124,32 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): { "description": "(in case you dont want to commit to 7/7 days a week)", "id": "working-days-only", - "label": "5/7 days a week" + "label": "5/7 days a week", + "points": 0 }, { "description": "", "id": "vegan", "label": "Vegan", + "points": 20, "requires": [ { "description": "", "id": "vegetarian", "label": "Vegetarian", + "points": 20, "requires": [ { "description": "", "id": "pescatarian", "label": "Pescatarian", + "points": 5, "requires": [ { "description": "", "id": "no-beef", - "label": "No Beef" + "label": "No Beef", + "points": 5 } ] } @@ -154,11 +159,13 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): "description": "", "id": "no-dairy", "label": "No Dairy", + "points": 10, "requires": [ { "description": "", "id": "no-cheese", - "label": "No Cheese" + "label": "No Cheese", + "points": 10 } ] } @@ -200,7 +207,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): prt_payload = { # it would be nice that the commitment is randomly generated based on certain # options - "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"vegan\"]}", + "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"pescatarian\", \"no-beef\"]}", "pathParameters": { "crowdactionID": cid }, From c3269e13944251c6e8be3404107b37fad1633a54 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Sat, 18 Jun 2022 10:33:38 +0200 Subject: [PATCH 56/67] small changes to the badge award script these changes are related mainly to the crowdaction_id, and also the deletion of event and permission from lambda --- badges/eventbus.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index e210e31..19ea272 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -7,6 +7,7 @@ import boto3 import os from dynamodb import * + e_client = boto3.client('events') l_client = boto3.client('lambda') @@ -16,6 +17,7 @@ def compute_badge_award(points, reward_list): + print('venezuela') """ There is an assumption about the order of the reward_list. This is taken into @@ -49,11 +51,10 @@ def lambda_handler(event, context): target_name = 'lambda_cron_test_end_date' single_table = 'collaction-dev-edreinoso-SingleTable-BAXICTFSQ4WV' profile_table = 'collaction-dev-edreinoso-ProfileTable-XQEJJNBK6UUY' - # crowdaction_id = event['resources'][0].split('/')[1] - crowdaction_id = 'sustainability#food#185f66fd' - # participant_sk = "prt#act#" + crowdaction_id - print('Lambda Crontab!', event['resources'] - [0].split('/')[1].replace('_', '#')) + crowdaction_id = event['resources'][0].split( + '/')[1].replace('_', '#') # prod + # crowdaction_id = 'sustainability#food#185f66fd' # test + print('Lambda Crontab!', crowdaction_id) """ POINT CALCULATION LOGIC @@ -61,15 +62,16 @@ def lambda_handler(event, context): # 1. fetch the badge scale for crowdaction ✅ badge_scale = ddb.get_item(single_table, crowdaction_id) + # print(badge_scale) tree = badge_scale['Item']['commitment_options']['L'] for reward in badge_scale['Item']['badges']['L']: badge_reward_list.append(reward['N']) - # print(badge_reward_list) # verfying the badge reward list + print(badge_reward_list) # verfying the badge reward list # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) - # print(commit_dict) # verifying the dictionary convertion + print(commit_dict) # verifying the dictionary convertion # 3. go through all participants ✅ participant_list = ddb.query(single_table, crowdaction_id) @@ -89,7 +91,9 @@ def lambda_handler(event, context): "prt": prt_lvl, "points": usr_prt_counter } + print(usr_obj) # if prt_lvl in commit_dict: # would I be assuming that a user would always have a participation + print('helloworld') usr_obj['badge'] = compute_badge_award( usr_prt_counter, badge_reward_list) user_prt_list.append(usr_obj) @@ -100,6 +104,18 @@ def lambda_handler(event, context): for usr in user_prt_list: ddb.update(profile_table, usr['userid'], usr['badge'], crowdaction_id) + # 6. delete event ✅ + crowdaction_id_e = crowdaction_id.replace('#', '_') + e_client.delete_rule( + Name=crowdaction_id_e, + ) + + # 7. delete permission ✅ + l_client.remove_permission( + FunctionName=target_name, + StatementId=crowdaction_id_e, + ) + return { 'statusCode': 200, 'body': json.dumps('Crowdaction Ended!') From 7abd4a3131a0c103e05c73c8eab0448fcd555e25 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 21 Jun 2022 13:05:17 +0200 Subject: [PATCH 57/67] modified test script created a different class for the different ops, create user, crowdaction and profile --- scripts/badges/api.py | 249 ++++++--------------------------------- scripts/badges/create.py | 169 ++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 216 deletions(-) create mode 100644 scripts/badges/create.py diff --git a/scripts/badges/api.py b/scripts/badges/api.py index 4f55268..6977f6b 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -3,240 +3,57 @@ if the API is not available, then try to use boto3 to put records in DynamoDB """ -from datetime import datetime -from datetime import timedelta -import json +from create import profile, crowdaction, participation import string import random -import boto3 -import requests -l_client = boto3.client('lambda') +create_usr = profile() +create_cwd = crowdaction() +create_prt = participation() def id_generator(size=6, chars=string.ascii_letters + string.digits): return ''.join(random.choice(chars) for _ in range(size)) -""" - CREATE USER - put user in profile dynamodb - randomID for the user - if the API is not working, - the work around is to use boto3 - or event the other work would be - to use an event directly - the idea is to create couple of users, - save them in a list to use later in the - participation portion of the script -""" +# Goal! +# 5 users +# 1 crowdaction +# 5 different commitments -""" - for loop - post - multiple users - save them into a list - along with their commitment -""" commitment_arr = [ - "no-diary", - "no-cheese", - "no-beef", - "pescatarian", - "vegetarian", - "vegan" + ["no-cheese"], + ["no-cheese", "no-diary"], + ["no-beef"], + ["no-beef", "pescatarian"], + ["no-beef", "pescatarian", "vegeterian"], + ["no-beef", "pescatarian", "vegeterian", "vegan"] ] -randomNum = random.randrange(4) # this should be inside for loop -# usr_list = [ -# {"id": usr_id, "commitment": commitment_arr[randomNum]} -# ] - -# randomly create a user_id -usr_id = id_generator(28) -usr_payload = { - "body": "{\"displayname\": \"Timothy\", \"city\": \"New York\", \"country\": \"USA\", \"bio\": \"Hi, I'm Timothy\"}", - "pathParameters": { - "userID": usr_id - }, - "requestContext": { - "authorizer": { - "jwt": { - "claims": { - "name": "Timothy", - "user_id": usr_id, - "sub": usr_id, - "phone_number": "+31612345678" - } - } - }, - "http": { - "method": "POST" - } - } -} - -# uri = 'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/cms/crowdactions' -# user = requests.post(uri, json=usr_payload) -# print(user.json()) -res = l_client.invoke( - FunctionName='collaction-dev-edreinoso-ProfileCRUDFunction-gLFLlRBye4eA', - InvocationType='RequestResponse', - Payload=bytes(json.dumps(usr_payload), encoding='utf8'), -) -print(res) +usr_list = [] -""" - CREATE CROWDACTION -""" -current_time = datetime.now() - -gmt_time = datetime.now() - timedelta(hours=2) # converting time to GMT -crowdacticon_date_end = gmt_time + timedelta(minutes=3) -crowdacticon_date_limit = gmt_time + timedelta(minutes=4) -# datetime.now().strftime("%Y-%m-%d") -crowdaction_start_time = gmt_time.replace(microsecond=0) -crowdaction_expiry_time = crowdacticon_date_end.replace(microsecond=0) -crowdaction_join_limit = crowdacticon_date_limit.replace(microsecond=0) - -category = id_generator(8) -subcategory = id_generator(8) - -cwr_payload = { - "title": "querico", - "description": "test1", - "category": category, - "subcategory": subcategory, - "location": "test1", - "date_end": str(crowdaction_expiry_time), - "date_start": str(crowdaction_start_time), - "date_limit_join": "2022-06-19", - # "date_limit_join": str(crowdaction_join_limit), - "password_join": "", - "images": { - "card": "hello", - "banner": "world" - }, - "badges": [20, 40, 60, 80], - "participation_count": 0, - "top_participants": [], - "commitment_options": [ - { - "description": "(in case you dont want to commit to 7/7 days a week)", - "id": "working-days-only", - "label": "5/7 days a week", - "points": 0 - }, - { - "description": "", - "id": "vegan", - "label": "Vegan", - "points": 20, - "requires": [ - { - "description": "", - "id": "vegetarian", - "label": "Vegetarian", - "points": 20, - "requires": [ - { - "description": "", - "id": "pescatarian", - "label": "Pescatarian", - "points": 5, - "requires": [ - { - "description": "", - "id": "no-beef", - "label": "No Beef", - "points": 5 - } - ] - } - ] - }, - { - "description": "", - "id": "no-dairy", - "label": "No Dairy", - "points": 10, - "requires": [ - { - "description": "", - "id": "no-cheese", - "label": "No Cheese", - "points": 10 - } - ] - } - ] - } - ], -} - -uri = 'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/cms/crowdactions' - -# # print(cwr_payload) - -res = requests.post(uri, json=cwr_payload) -crowdaction = res.json() -cid = crowdaction['data']['crowdactionID'] -print(cid) +# create users +for i in range(0, 5): + usr_id = id_generator(28) + randomNum = random.randrange(6) -""" - # CREATE PARTICIPATION - take the newly created user ID - take the newly created crowdaction ID - I would like to be returing the crowdaction itself - not necessary if I end up using the - category and - subcategory - variables - this could be a for loop that iterates - through a stack of users (with their ID) -""" + usr_obj = { + "id": usr_id, + "commitment": commitment_arr[randomNum] + } -# TODO: complete this loop -""" - for n in list of users - from list - grab the id - grab the commimtment -""" + usr_list.append(usr_obj) -prt_payload = { - # it would be nice that the commitment is randomly generated based on certain - # options - "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":[\"pescatarian\", \"no-beef\"]}", - "pathParameters": { - "crowdactionID": cid - }, - "requestContext": { - "authorizer": { - "jwt": { - "claims": { - "name": "Hello World", - "user_id": usr_id, - "sub": usr_id, - "phone_number": "+31612345678" - } - } - }, - "http": { - "method": "POST" - } - } -} + res = create_usr(usr_id) + + print('user id:', usr_id, 'res:', res) -# uri = f'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/crowdactions/{crowdactionId}/participation' -# # for n in range(0,10): -# participation = requests.post(uri, json=prt_payload) -# print(participation.json()) +# create crowdaction +cid = create_cwd() -res = l_client.invoke( - FunctionName='collaction-dev-edreinoso-ParticipationFunction-zc9MRMJVkIjO', - InvocationType='RequestResponse', - Payload=bytes(json.dumps(prt_payload), encoding='utf8'), -) +# create participation +for n in range(0, len(usr_list)): + res = create_prt(cid, usr_list[n]['id']) -print(res) + print('res:', res) diff --git a/scripts/badges/create.py b/scripts/badges/create.py new file mode 100644 index 0000000..7522f23 --- /dev/null +++ b/scripts/badges/create.py @@ -0,0 +1,169 @@ +""" + Create endpoints file +""" +from datetime import datetime +from datetime import timedelta +import json +import boto3 +import requests + +l_client = boto3.client('lambda') + + +class create: + def profile(self, usr_id): + self.usr_id = usr_id + usr_payload = { + "body": "{\"displayname\": \"Timothy\", \"city\": \"New York\", \"country\": \"USA\", \"bio\": \"Hi, I'm Timothy\"}", + "pathParameters": { + "userID": usr_id + }, + "requestContext": { + "authorizer": { + "jwt": { + "claims": { + "name": "Timothy", + "user_id": usr_id, + "sub": usr_id, + "phone_number": "+31612345678" + } + } + }, + "http": { + "method": "POST" + } + } + } + + res = l_client.invoke( + FunctionName='collaction-dev-edreinoso-ProfileCRUDFunction-gLFLlRBye4eA', + InvocationType='RequestResponse', + Payload=bytes(json.dumps(usr_payload), encoding='utf8'), + ) + return res + + def crowdaction(self,): + gmt_time = datetime.now() - timedelta(hours=2) # converting time to GMT + crowdacticon_date_end = gmt_time + timedelta(minutes=3) + crowdacticon_date_limit = gmt_time + timedelta(minutes=4) + + crowdaction_start_time = gmt_time.replace(microsecond=0) + crowdaction_expiry_time = crowdacticon_date_end.replace(microsecond=0) + crowdaction_join_limit = crowdacticon_date_limit.replace(microsecond=0) + + print(crowdaction_expiry_time, crowdaction_join_limit) + + category = id_generator(8) + subcategory = id_generator(8) + + cwr_payload = { + "title": "querico", + "description": "test1", + "category": category, + "subcategory": subcategory, + "location": "test1", + "date_end": str(crowdaction_expiry_time), + "date_start": str(crowdaction_start_time), + "date_limit_join": "2022-06-19", + # "date_limit_join": str(crowdaction_join_limit), # this should be tested + "password_join": "", + "images": { + "card": "hello", + "banner": "world" + }, + "badges": [20, 40, 60, 80], + "participation_count": 0, + "top_participants": [], + "commitment_options": [ + { + "description": "(in case you dont want to commit to 7/7 days a week)", + "id": "working-days-only", + "label": "5/7 days a week", + "points": 0 + }, + { + "description": "", + "id": "vegan", + "label": "Vegan", + "points": 20, + "requires": [ + { + "description": "", + "id": "vegetarian", + "label": "Vegetarian", + "points": 20, + "requires": [ + { + "description": "", + "id": "pescatarian", + "label": "Pescatarian", + "points": 5, + "requires": [ + { + "description": "", + "id": "no-beef", + "label": "No Beef", + "points": 5 + } + ] + } + ] + }, + { + "description": "", + "id": "no-dairy", + "label": "No Dairy", + "points": 10, + "requires": [ + { + "description": "", + "id": "no-cheese", + "label": "No Cheese", + "points": 10 + } + ] + } + ] + } + ], + } + + uri = 'https://5y310ujdy1.execute-api.eu-central-1.amazonaws.com/dev/cms/crowdactions' + + res = requests.post(uri, json=cwr_payload) + crowdaction = res.json() + cid = crowdaction['data']['crowdactionID'] + return cid + + def participation(self, cid, usr_id): + self.cid = cid + self.usr_id = usr_id + + prt_payload = { + "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":\"f{usr_list[n]['commitment']}\"}", + "pathParameters": { + "crowdactionID": cid + }, + "requestContext": { + "authorizer": { + "jwt": { + "claims": { + "name": "Hello World", + "user_id": usr_id, + "sub": usr_id, + "phone_number": "+31612345678" + } + } + }, + "http": { + "method": "POST" + } + } + } + + res = l_client.invoke( + FunctionName='collaction-dev-edreinoso-ParticipationFunction-zc9MRMJVkIjO', + InvocationType='RequestResponse', + Payload=bytes(json.dumps(prt_payload), encoding='utf8'), + ) + return res From 19e9d93e835d3508a7ed36cf8e7f3a33a6b599cf Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 21 Jun 2022 13:07:37 +0200 Subject: [PATCH 58/67] passed category and subcategory to the create class --- scripts/badges/api.py | 4 +++- scripts/badges/create.py | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index 6977f6b..2ef60aa 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -50,7 +50,9 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): print('user id:', usr_id, 'res:', res) # create crowdaction -cid = create_cwd() +category = id_generator(8) +subcategory = id_generator(8) +cid = create_cwd(category, subcategory) # create participation for n in range(0, len(usr_list)): diff --git a/scripts/badges/create.py b/scripts/badges/create.py index 7522f23..49f673a 100644 --- a/scripts/badges/create.py +++ b/scripts/badges/create.py @@ -42,7 +42,10 @@ def profile(self, usr_id): ) return res - def crowdaction(self,): + def crowdaction(self, category, subcategory): + self.category = category + self.subcategory = subcategory + gmt_time = datetime.now() - timedelta(hours=2) # converting time to GMT crowdacticon_date_end = gmt_time + timedelta(minutes=3) crowdacticon_date_limit = gmt_time + timedelta(minutes=4) @@ -53,9 +56,6 @@ def crowdaction(self,): print(crowdaction_expiry_time, crowdaction_join_limit) - category = id_generator(8) - subcategory = id_generator(8) - cwr_payload = { "title": "querico", "description": "test1", From c78179b4523a38cb4d87f4908c5854556b454535 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 21 Jun 2022 13:27:07 +0200 Subject: [PATCH 59/67] class and function changes in the test class --- scripts/badges/api.py | 14 ++++++-------- scripts/badges/create.py | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index 2ef60aa..264f512 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -3,14 +3,12 @@ if the API is not available, then try to use boto3 to put records in DynamoDB """ -from create import profile, crowdaction, participation +from create import test import string import random -create_usr = profile() -create_cwd = crowdaction() -create_prt = participation() +create = test() # init test class def id_generator(size=6, chars=string.ascii_letters + string.digits): @@ -45,17 +43,17 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): usr_list.append(usr_obj) - res = create_usr(usr_id) + res = create.profile(usr_id) print('user id:', usr_id, 'res:', res) # create crowdaction category = id_generator(8) subcategory = id_generator(8) -cid = create_cwd(category, subcategory) +cid = create.crowdaction(category, subcategory) -# create participation +# # create participation for n in range(0, len(usr_list)): - res = create_prt(cid, usr_list[n]['id']) + res = create.participation(cid, usr_list[n]['id']) print('res:', res) diff --git a/scripts/badges/create.py b/scripts/badges/create.py index 49f673a..8a12cbf 100644 --- a/scripts/badges/create.py +++ b/scripts/badges/create.py @@ -10,7 +10,7 @@ l_client = boto3.client('lambda') -class create: +class test: def profile(self, usr_id): self.usr_id = usr_id usr_payload = { From ea34179657ac261b74ae7e93b456342b004b50b4 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 21 Jun 2022 13:32:21 +0200 Subject: [PATCH 60/67] updated the eventbus for badge award copied the latest changes from the lambda function --- badges/dynamodb.py | 14 +++++--------- badges/eventbus.py | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/badges/dynamodb.py b/badges/dynamodb.py index 18d6fee..5ac8f63 100644 --- a/badges/dynamodb.py +++ b/badges/dynamodb.py @@ -3,9 +3,7 @@ class ddb_ops(): - """ - Get Item - """ + """Get Item""" def get_item(self, table, crowdaction_id): self.table = table @@ -20,9 +18,7 @@ def get_item(self, table, crowdaction_id): ) return res - """ - Query Items - """ + """Query Items""" def query(self, table, crowdaction_id): self.table = table @@ -37,10 +33,8 @@ def query(self, table, crowdaction_id): }, ) return res - """ - Update Items - """ + """Update Items""" def update(self, table, usr_id, reward, crowdaction_id): self.table = table @@ -48,6 +42,8 @@ def update(self, table, usr_id, reward, crowdaction_id): self.reward = reward self.crowdaction_id = crowdaction_id + print("update", table, usr_id, reward, crowdaction_id) + d_client.update_item( TableName=table, Key={ diff --git a/badges/eventbus.py b/badges/eventbus.py index 19ea272..16900d5 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -62,7 +62,7 @@ def lambda_handler(event, context): # 1. fetch the badge scale for crowdaction ✅ badge_scale = ddb.get_item(single_table, crowdaction_id) - # print(badge_scale) + print(badge_scale) tree = badge_scale['Item']['commitment_options']['L'] for reward in badge_scale['Item']['badges']['L']: @@ -75,7 +75,7 @@ def lambda_handler(event, context): # 3. go through all participants ✅ participant_list = ddb.query(single_table, crowdaction_id) - # print(participant_list) + print(participant_list) # 4. map user commitment level ✅ user_prt_list = [] # list required to store individual participations @@ -104,13 +104,26 @@ def lambda_handler(event, context): for usr in user_prt_list: ddb.update(profile_table, usr['userid'], usr['badge'], crowdaction_id) - # 6. delete event ✅ + """ + CLEANING UP TARGETS AND EVENTS + """ + crowdaction_id_e = crowdaction_id.replace('#', '_') + + # 6. delete targets ✅ + e_client.remove_targets( + Rule=crowdaction_id_e, + Ids=[ + target_name, + ], + ) + + # 7. delete event ✅ e_client.delete_rule( Name=crowdaction_id_e, ) - # 7. delete permission ✅ + # 8. delete permission ✅ l_client.remove_permission( FunctionName=target_name, StatementId=crowdaction_id_e, From 8156a80a1654f429c886c2f34107b93aa31a8f6f Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Tue, 21 Jun 2022 13:33:57 +0200 Subject: [PATCH 61/67] minor changes to the api.py test script cleaned up a bit with some comments and terminologies --- scripts/badges/api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index 264f512..ce02197 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -18,7 +18,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): # Goal! # 5 users # 1 crowdaction -# 5 different commitments +# 5 different participations commitment_arr = [ ["no-cheese"], @@ -31,7 +31,7 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): usr_list = [] -# create users +"""create users""" for i in range(0, 5): usr_id = id_generator(28) randomNum = random.randrange(6) @@ -47,12 +47,12 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): print('user id:', usr_id, 'res:', res) -# create crowdaction +"""create crowdaction""" category = id_generator(8) subcategory = id_generator(8) cid = create.crowdaction(category, subcategory) -# # create participation +"""create participation""" for n in range(0, len(usr_list)): res = create.participation(cid, usr_list[n]['id']) From 8659ee76f436866a969a7cb89f1320a3118dae87 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 22 Jun 2022 12:52:17 +0200 Subject: [PATCH 62/67] ignoring cached python files in test directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9a84bb0..8b62380 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ _ignored/ .DS_Store .idea -samconfig.yaml \ No newline at end of file +samconfig.yaml +scripts/badges/__pycache__/create.cpython-39.pyc From 0edc755d7d2a74d98a204f73ad42662213470ea3 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Wed, 22 Jun 2022 13:28:48 +0200 Subject: [PATCH 63/67] dynamic commitment in test script --- scripts/badges/api.py | 68 +++++++++++++++++++++++----------------- scripts/badges/create.py | 13 ++++++-- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index ce02197..0d03ce3 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -6,7 +6,7 @@ from create import test import string import random - +import json create = test() # init test class @@ -19,41 +19,51 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): # 5 users # 1 crowdaction # 5 different participations +def main(): + commitment_arr = [ + ["no-cheese"], + ["no-cheese", "no-diary"], + ["no-beef"], + ["no-beef", "pescatarian"], + ["no-beef", "pescatarian", "vegeterian"], + ["no-beef", "pescatarian", "vegeterian", "vegan"] + ] + + usr_list = [] + + """create users""" + for i in range(0, 1): + usr_id = id_generator(28) + randomNum = random.randrange(6) + + usr_obj = { + "id": usr_id, + "commitment": commitment_arr[randomNum] + } -commitment_arr = [ - ["no-cheese"], - ["no-cheese", "no-diary"], - ["no-beef"], - ["no-beef", "pescatarian"], - ["no-beef", "pescatarian", "vegeterian"], - ["no-beef", "pescatarian", "vegeterian", "vegan"] -] + usr_list.append(usr_obj) -usr_list = [] + res = create.profile(usr_id) -"""create users""" -for i in range(0, 5): - usr_id = id_generator(28) - randomNum = random.randrange(6) + print('user id:', usr_id, 'res:', res) - usr_obj = { - "id": usr_id, - "commitment": commitment_arr[randomNum] - } + print() - usr_list.append(usr_obj) + """create crowdaction""" + category = id_generator(8) + subcategory = id_generator(8) + cid = create.crowdaction(category, subcategory) - res = create.profile(usr_id) + print() - print('user id:', usr_id, 'res:', res) + """create participation""" + for n in range(0, len(usr_list)): + res = create.participation( + cid, usr_list[n]['id'], usr_list[n]['commitment']) -"""create crowdaction""" -category = id_generator(8) -subcategory = id_generator(8) -cid = create.crowdaction(category, subcategory) + print('user id:', usr_list[n]['id'], 'commitment:', + usr_list[n]['commitment'], 'res:', res) -"""create participation""" -for n in range(0, len(usr_list)): - res = create.participation(cid, usr_list[n]['id']) - print('res:', res) +if __name__ == '__main__': + main() diff --git a/scripts/badges/create.py b/scripts/badges/create.py index 8a12cbf..00d95c4 100644 --- a/scripts/badges/create.py +++ b/scripts/badges/create.py @@ -10,7 +10,7 @@ l_client = boto3.client('lambda') -class test: +class test(): def profile(self, usr_id): self.usr_id = usr_id usr_payload = { @@ -135,12 +135,19 @@ def crowdaction(self, category, subcategory): cid = crowdaction['data']['crowdactionID'] return cid - def participation(self, cid, usr_id): + def participation(self, cid, usr_id, commitment): self.cid = cid self.usr_id = usr_id + self.commitment = commitment + + # dynamic commitments + body = { + "password": "myEvent-myCompany2021", + "commitments": commitment + } prt_payload = { - "body": "{\"password\":\"myEvent-myCompany2021\", \"commitments\":\"f{usr_list[n]['commitment']}\"}", + "body": json.dumps(body), "pathParameters": { "crowdactionID": cid }, From 2f647f25b3b40d143dd418786ba3c64c883bcc9b Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 23 Jun 2022 00:23:58 +0200 Subject: [PATCH 64/67] fixed typos with the commitments these errors were causing validation errors when recording the participation --- scripts/badges/api.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index 0d03ce3..fa0d91a 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -22,17 +22,17 @@ def id_generator(size=6, chars=string.ascii_letters + string.digits): def main(): commitment_arr = [ ["no-cheese"], - ["no-cheese", "no-diary"], + ["no-dairy", "no-cheese"], ["no-beef"], - ["no-beef", "pescatarian"], - ["no-beef", "pescatarian", "vegeterian"], - ["no-beef", "pescatarian", "vegeterian", "vegan"] + ["pescatarian", "no-beef"], + ["vegetarian", "pescatarian", "no-beef"], + ["vegan", "vegetarian", "pescatarian", "no-beef"], ] usr_list = [] """create users""" - for i in range(0, 1): + for i in range(0, 5): usr_id = id_generator(28) randomNum = random.randrange(6) From 0b23bc502e76c8577b0e68d695321f12bdc78a5c Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 23 Jun 2022 00:25:29 +0200 Subject: [PATCH 65/67] created delete eventbridge rule file to automatically delete all the test cases that are created from the script --- scripts/badges/delete_rules.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 scripts/badges/delete_rules.py diff --git a/scripts/badges/delete_rules.py b/scripts/badges/delete_rules.py new file mode 100644 index 0000000..25fc197 --- /dev/null +++ b/scripts/badges/delete_rules.py @@ -0,0 +1,10 @@ +import boto3 + +client = boto3.client('events') + +response = client.list_rules() + +for rules in response['Rules']: + client.delete_rule( + Name=rules['Name'] + ) From 8f65e11b319b657f82e97edf94d77a3baa4bef23 Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 23 Jun 2022 11:42:17 +0200 Subject: [PATCH 66/67] modified the commitment level in test script this change should represent the correct interpretation of the commitment tree, otherwise there would be a validation error from the backend --- scripts/badges/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/badges/api.py b/scripts/badges/api.py index fa0d91a..b256861 100644 --- a/scripts/badges/api.py +++ b/scripts/badges/api.py @@ -26,7 +26,7 @@ def main(): ["no-beef"], ["pescatarian", "no-beef"], ["vegetarian", "pescatarian", "no-beef"], - ["vegan", "vegetarian", "pescatarian", "no-beef"], + ["vegan", "vegetarian", "pescatarian", "no-beef", "no-dairy", "no-cheese"], ] usr_list = [] From 8ccbf6ffedc86d1c451d99223ad3e2c21066cf9c Mon Sep 17 00:00:00 2001 From: Ed Reinoso Date: Thu, 23 Jun 2022 11:55:31 +0200 Subject: [PATCH 67/67] changed id to remove target from the rule --- badges/eventbus.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/badges/eventbus.py b/badges/eventbus.py index 16900d5..87d1ad7 100644 --- a/badges/eventbus.py +++ b/badges/eventbus.py @@ -17,7 +17,6 @@ def compute_badge_award(points, reward_list): - print('venezuela') """ There is an assumption about the order of the reward_list. This is taken into @@ -53,7 +52,6 @@ def lambda_handler(event, context): profile_table = 'collaction-dev-edreinoso-ProfileTable-XQEJJNBK6UUY' crowdaction_id = event['resources'][0].split( '/')[1].replace('_', '#') # prod - # crowdaction_id = 'sustainability#food#185f66fd' # test print('Lambda Crontab!', crowdaction_id) """ @@ -62,12 +60,11 @@ def lambda_handler(event, context): # 1. fetch the badge scale for crowdaction ✅ badge_scale = ddb.get_item(single_table, crowdaction_id) - print(badge_scale) tree = badge_scale['Item']['commitment_options']['L'] for reward in badge_scale['Item']['badges']['L']: badge_reward_list.append(reward['N']) - print(badge_reward_list) # verfying the badge reward list + # print(badge_reward_list) # verfying the badge reward list # 2. restructure the tree to a dictionary ✅ tree_recursion(tree) @@ -93,7 +90,6 @@ def lambda_handler(event, context): } print(usr_obj) # if prt_lvl in commit_dict: # would I be assuming that a user would always have a participation - print('helloworld') usr_obj['badge'] = compute_badge_award( usr_prt_counter, badge_reward_list) user_prt_list.append(usr_obj) @@ -102,7 +98,8 @@ def lambda_handler(event, context): # 5. award badge ✅ for usr in user_prt_list: - ddb.update(profile_table, usr['userid'], usr['badge'], crowdaction_id) + ddb.update( + profile_table, usr['userid'], usr['badge'], crowdaction_id) """ CLEANING UP TARGETS AND EVENTS @@ -110,25 +107,25 @@ def lambda_handler(event, context): crowdaction_id_e = crowdaction_id.replace('#', '_') - # 6. delete targets ✅ + # 6. delete permission ✅ + l_client.remove_permission( + FunctionName=target_name, + StatementId=crowdaction_id_e, + ) + + # 7. delete targets ✅ e_client.remove_targets( Rule=crowdaction_id_e, Ids=[ - target_name, + crowdaction_id_e, ], ) - # 7. delete event ✅ + # 8. delete event ✅ e_client.delete_rule( Name=crowdaction_id_e, ) - # 8. delete permission ✅ - l_client.remove_permission( - FunctionName=target_name, - StatementId=crowdaction_id_e, - ) - return { 'statusCode': 200, 'body': json.dumps('Crowdaction Ended!')