Skip to content

Commit adf04fb

Browse files
tarashagarwalEthM370devksingh4tarashagarwalCoderCCM
authored
Linkry UI main (#110)
* New paidevent routes * Fixed * Rename paidevents.ts to paidEvents.ts Fixed case issues during git push * TestCasesforGet & POST and DELETE for ticket * New Post Schema * Fix path routes * setup the scaffolding for linkry routes * don't run github actions on draft PRs * setup the redirect route * fix tests * Adding Routes and Pages for Linkry New UI * Adding a API to fetch data from Dyanmo * UI for Linkry - Step 1 * UI for Linkry - Step 2 * UI for Linkry - Step 3 * paidEvent POST merch update * Encoding URL in Delete Request * New Linkry/Add UI Implemented * Start of linkry createRequest * New UI Implemented * Frontend-Backend Integration: New UI, Fix Delete * Adding ACM Groups to Configurations & Fetching them for Backend and Frontend Respectively * Maintenance * New UI Adjustment + Integration via retrieving Linkry Group Setting from Config * Convert Add to Transaction, Validate slug does not already exist on Create * Validate access group list against env config * Do not allow the user to create a reserved slug * Use Zulu Timestamps * Minor Timestamp Change * Initial Implementation of Fetch Link Data * Updating View Screen To Remove Group# or OWNER# from the view screen * Updating Error Message in the UI * New UI Fix implemented : Current Redirect set to localhost for LOCAL testing * Add listGroupIDsByEmail * Updating User Inteface and few updates at the backend * Adding Cancel Button on Delete Dialog Box * Adding Is Edited Flag to Help Updates at the Backend * Regression Fixes * Updading UI, Improving API & UI for Editing Links, Updating API fto view Links * Minor Fixes * Updating UI * UI Updates * Improving Delegated Links Fetch Algorithm and some UI Enhancements * Bug Fix URL regex only accepts https:// * Debug comment * Convert to Group UUIDs * Visit Count Feature Implemented + Edit Feature Bug Fix * Improve Typecasting; Begin Code Cleanup * Improve Typecasting; pt. 2 * Fix Typecasting pt. 3 * Delegated Link Error on Edit Fix * Merge * Delete delegated ownertag * Request Pre-Validation and Code Cleanup * Validate User Access for Slug Edit and Delete * Allow for Links with No Access Groups * Bug fix : Multiple Delegated entry for the same delegated link * Removing Owner id From Delgated Links Access Groups * Fixes * Fixes * Progressing On Admin Page * Added Owner To the Admin Links * Improving Readiblity of the APIs * Adding Loader Screen to The Links View Dashboards * Add link to Admin Panel and navigate back to source page after edit completion * Add link to Admin Panel and navigate back to source page after save completion * Admin API Fixes * Reset Button Only Clickable when count is non zero * Fixing Counter issue * Minor buG fix * Dark Mode Fixed & dev/prod set redirect url domain * Dark Mode for Admin Screen Fixed * Fix admin page authentication requirement * Fixing The User Group Fetch Algo * Main Merge Updates * Updating Linke-Shortener name to Linkry and adding Test Files for Linkry * Adding a Test Case & Some cleanup * Fixing few APIS * Minor Readibility Updates * Merge Updates * Merge Updates * Delete legacy paidevent development * Fixed typecheck in Adminpage & created new vitest group for linkadmin and corrected unit test * Adding Cache Rules and Tests * Deployment Trigges * DyanmoDb Permission Updates * Updates * dev redirect domain changed to core.aws.qa... * minor changes * cfn edge function * fix domain name association * update * fix * use edge function for edge kv * use cloudfront KV store to handle redirect mechanism instead of dynamo * mock cloudfront KV correctly * mock getLinkryKvArn * throw correct error for failing to get the KV arn * fix tests * try to bundle signature-v4-crt with the lambda * move aws_crt into the bundle * fix makefile * enable cloudfront kv store IAM access * update schemas * support featured tag * redesign backend * add better error catching * fix tests * update behavior * cleanup * log * fix unit testing * fix UI papercuts * clear session storage on logout * fix unit tests --------- Co-authored-by: Ethan Ma <[email protected]> Co-authored-by: Dev Singh <[email protected]> Co-authored-by: tarashagarwal <[email protected]> Co-authored-by: Connor Magnuson <[email protected]> Co-authored-by: Tarash Agarwal <[email protected]> Co-authored-by: Dev Singh <[email protected]>
1 parent ce112c6 commit adf04fb

27 files changed

+3591
-442
lines changed

Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ build: src/ cloudformation/ docs/
5959
cp -r src/api/resources/ dist/api/resources
6060
rm -rf dist/lambda/sqs
6161
sam build --template-file cloudformation/main.yml
62+
mkdir -p .aws-sam/build/AppApiLambdaFunction/node_modules/aws-crt/
63+
cp -r node_modules/aws-crt/dist .aws-sam/build/AppApiLambdaFunction/node_modules/aws-crt
6264

6365
local:
6466
VITE_BUILD_HASH=$(GIT_HASH) yarn run dev
@@ -80,7 +82,7 @@ deploy_dev: check_account_dev build
8082
invalidate_cloudfront:
8183
@echo "Creating CloudFront invalidation..."
8284
$(eval DISTRIBUTION_ID := $(shell aws cloudformation describe-stacks --stack-name $(application_key) --query "Stacks[0].Outputs[?OutputKey=='CloudfrontDistributionId'].OutputValue" --output text))
83-
$(eval DISTRIBUTION_ID_2 := $(shell aws cloudformation describe-stacks --stack-name $(application_key) --query "Stacks[0].Outputs[?OutputKey=='CloudfrontSecondaryDistributionId'].OutputValue" --output text))
85+
$(eval DISTRIBUTION_ID_2 := $(shell aws cloudformation describe-stacks --stack-name $(application_key) --query "Stacks[0].Outputs[?OutputKey=='CloudfrontIcalDistributionId'].OutputValue" --output text))
8486
$(eval INVALIDATION_ID := $(shell aws cloudfront create-invalidation --distribution-id $(DISTRIBUTION_ID) --paths "/*" --query 'Invalidation.Id' --output text --no-cli-page))
8587
$(eval INVALIDATION_ID_2 := $(shell aws cloudfront create-invalidation --distribution-id $(DISTRIBUTION_ID_2) --paths "/*" --query 'Invalidation.Id' --output text --no-cli-page))
8688
@echo "Waiting on job $(INVALIDATION_ID)..."

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ This repository is split into multiple parts:
77
## Getting Started
88
You will need node>=22 installed, as well as the AWS CLI and the AWS SAM CLI. The best way to work with all of this is to open the environment in a container within your IDE (VS Code should prompt you to do so: use "Clone in Container" for best performance). This container will have all needed software installed.
99

10-
Then, run `make install` to install all packages, and `make local` to start the UI and API servers! The UI will be accessible on `http://localhost:5173/` and the API on `http://localhost:8080/`.
10+
Then, run `make install` to install all packages, and `make local` to start the UI and API servers! The UI will be accessible on `http://localhost:5173/` and the API on `http://localhost:8080/`.

cloudformation/iam.yml

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Parameters:
1515
Type: String
1616
SqsQueueArn:
1717
Type: String
18+
LinkryKvArn:
19+
Type: String
1820

1921
Conditions:
2022
IsDev: !Equals [!Ref RunEnvironment, "dev"]
@@ -74,12 +76,14 @@ Resources:
7476
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-membership-external
7577
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-room-requests
7678
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-room-requests-status
79+
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-linkry
7780
# Index accesses
7881
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-stripe-links/index/*
7982
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-events/index/*
8083
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-merchstore-purchase-history/index/*
8184
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-room-requests/index/*
8285
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-room-requests-status/index/*
86+
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-linkry/index/*
8387

8488
- Sid: DynamoDBCacheAccess
8589
Effect: Allow
@@ -112,6 +116,12 @@ Resources:
112116
Resource:
113117
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-stripe-links/stream/*
114118
- Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-events/stream/*
119+
- Sid: CloudfrontKvStreamAccess
120+
Effect: Allow
121+
Action:
122+
- cloudfront-keyvaluestore:*
123+
Resource:
124+
- !Ref LinkryKvArn
115125

116126
# API Lambda IAM Role
117127
ApiLambdaIAMRole:

cloudformation/main.yml

+131-28
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Resources:
8787
LambdaFunctionName: !Sub ${ApplicationPrefix}-lambda
8888
SesEmailDomain: !FindInMap [General, !Ref RunEnvironment, SesDomain]
8989
SqsQueueArn: !GetAtt AppSQSQueues.Outputs.MainQueueArn
90+
LinkryKvArn: !GetAtt LinkryRecordsCloudfrontStore.Arn
9091

9192
AppLogGroups:
9293
Type: AWS::Serverless::Application
@@ -125,26 +126,6 @@ Resources:
125126
!FindInMap [ApiGwConfig, !Ref RunEnvironment, HostedZoneId]
126127
CloudfrontDomain: !GetAtt [AppIcalCloudfrontDistribution, DomainName]
127128

128-
LinkryDomainProxy:
129-
Type: AWS::Serverless::Application
130-
Properties:
131-
Location: ./custom-domain.yml
132-
Parameters:
133-
RunEnvironment: !Ref RunEnvironment
134-
RecordName: go
135-
GWBaseDomainName: !FindInMap
136-
- ApiGwConfig
137-
- !Ref RunEnvironment
138-
- EnvDomainName
139-
GWCertArn: !FindInMap
140-
- ApiGwConfig
141-
- !Ref RunEnvironment
142-
- EnvCertificateArn
143-
GWApiId: !Ref AppApiGateway
144-
GWHostedZoneId:
145-
!FindInMap [ApiGwConfig, !Ref RunEnvironment, HostedZoneId]
146-
CloudfrontDomain: !GetAtt [AppIcalCloudfrontDistribution, DomainName]
147-
148129
CoreUrlProd:
149130
Type: AWS::Serverless::Application
150131
Properties:
@@ -184,6 +165,8 @@ Resources:
184165
Variables:
185166
RunEnvironment: !Ref RunEnvironment
186167
EntraRoleArn: !GetAtt AppSecurityRoles.Outputs.EntraFunctionRoleArn
168+
LinkryKvArn: !GetAtt LinkryRecordsCloudfrontStore.Arn
169+
AWS_CRT_NODEJS_BINARY_RELATIVE_PATH: node_modules/aws-crt/dist/bin/linux-arm64-glibc/aws-crt-nodejs.node
187170
VpcConfig:
188171
Ipv6AllowedForDualStack: !If [ShouldAttachVpc, True, !Ref AWS::NoValue]
189172
SecurityGroupIds:
@@ -483,6 +466,34 @@ Resources:
483466
Projection:
484467
ProjectionType: "ALL"
485468

469+
LinkryRecordsTable:
470+
Type: "AWS::DynamoDB::Table"
471+
Properties:
472+
BillingMode: "PAY_PER_REQUEST"
473+
TableName: "infra-core-api-linkry"
474+
DeletionProtectionEnabled: !If [IsProd, true, false] # TODO: remove this
475+
PointInTimeRecoverySpecification:
476+
PointInTimeRecoveryEnabled: !If [IsProd, true, false]
477+
AttributeDefinitions:
478+
- AttributeName: "slug"
479+
AttributeType: "S"
480+
- AttributeName: "access"
481+
AttributeType: "S"
482+
KeySchema:
483+
- AttributeName: "slug"
484+
KeyType: "HASH"
485+
- AttributeName: "access"
486+
KeyType: "RANGE"
487+
GlobalSecondaryIndexes:
488+
- IndexName: "AccessIndex"
489+
KeySchema:
490+
- AttributeName: "access"
491+
KeyType: "HASH"
492+
- AttributeName: "slug"
493+
KeyType: "RANGE"
494+
Projection:
495+
ProjectionType: "ALL"
496+
486497
CacheRecordsTable:
487498
Type: "AWS::DynamoDB::Table"
488499
DeletionPolicy: "Retain"
@@ -831,13 +842,6 @@ Resources:
831842
OriginProtocolPolicy: https-only
832843
Enabled: true
833844
Aliases:
834-
- !Join
835-
- ""
836-
- - "go."
837-
- !FindInMap
838-
- ApiGwConfig
839-
- !Ref RunEnvironment
840-
- EnvDomainName
841845
- !Join
842846
- ""
843847
- - "ical."
@@ -875,6 +879,105 @@ Resources:
875879
HttpVersion: http2
876880
PriceClass: PriceClass_100
877881

882+
LinkryRecordsCloudfrontStore:
883+
Type: AWS::CloudFront::KeyValueStore
884+
Properties:
885+
Name: infra-core-api-cloudfront-linkry-kv
886+
887+
LinkryRecordsCloudfrontFunction:
888+
Type: 'AWS::CloudFront::Function'
889+
Properties:
890+
Name: infra-core-api-cloudfront-linkry-redir
891+
FunctionConfig:
892+
Comment: 'Linkry Redirect Cloudfront Function'
893+
Runtime: 'cloudfront-js-2.0'
894+
KeyValueStoreAssociations:
895+
- KeyValueStoreARN: !Sub '${LinkryRecordsCloudfrontStore.Arn}'
896+
FunctionCode: !Sub |
897+
import cf from 'cloudfront';
898+
const kvsId = '${LinkryRecordsCloudfrontStore.Id}';
899+
const kvs = cf.kvs(kvsId);
900+
901+
async function handler(event) {
902+
const request = event.request;
903+
const path = request.uri.replace(/^\/+/, '');
904+
let redirectUrl = "https://acm.illinois.edu/404";
905+
try {
906+
const value = await kvs.get(path);
907+
if (value) {
908+
redirectUrl = value;
909+
}
910+
} catch (err) {
911+
console.log('KVS key lookup failed');
912+
}
913+
var response = {
914+
statusCode: 302,
915+
statusDescription: 'Found',
916+
headers: {
917+
'location': { value: redirectUrl }
918+
}
919+
};
920+
return response;
921+
}
922+
AutoPublish: true
923+
924+
AppLinkryCloudfrontDistribution:
925+
Type: AWS::CloudFront::Distribution
926+
Properties:
927+
DistributionConfig:
928+
Enabled: true
929+
DefaultCacheBehavior:
930+
ViewerProtocolPolicy: redirect-to-https
931+
TargetOriginId: dummyOrigin
932+
ForwardedValues:
933+
QueryString: false
934+
Cookies:
935+
Forward: none
936+
FunctionAssociations:
937+
- EventType: viewer-request
938+
FunctionARN: !GetAtt LinkryRecordsCloudfrontFunction.FunctionARN
939+
Origins:
940+
- Id: dummyOrigin
941+
DomainName: example.com
942+
CustomOriginConfig:
943+
OriginProtocolPolicy: https-only
944+
Aliases:
945+
- !Join
946+
- ""
947+
- - "go."
948+
- !FindInMap
949+
- ApiGwConfig
950+
- !Ref RunEnvironment
951+
- EnvDomainName
952+
ViewerCertificate:
953+
AcmCertificateArn: !FindInMap
954+
- ApiGwConfig
955+
- !Ref RunEnvironment
956+
- EnvCertificateArn
957+
MinimumProtocolVersion: TLSv1.2_2021
958+
SslSupportMethod: sni-only
959+
HttpVersion: http2
960+
PriceClass: PriceClass_100
961+
962+
LinkryDomainProxy:
963+
Type: AWS::Serverless::Application
964+
Properties:
965+
Location: ./custom-domain.yml
966+
Parameters:
967+
RunEnvironment: !Ref RunEnvironment
968+
RecordName: go
969+
GWBaseDomainName: !FindInMap
970+
- ApiGwConfig
971+
- !Ref RunEnvironment
972+
- EnvDomainName
973+
GWCertArn: !FindInMap
974+
- ApiGwConfig
975+
- !Ref RunEnvironment
976+
- EnvCertificateArn
977+
GWApiId: !Ref AppApiGateway
978+
GWHostedZoneId:
979+
!FindInMap [ApiGwConfig, !Ref RunEnvironment, HostedZoneId]
980+
CloudfrontDomain: !GetAtt [AppLinkryCloudfrontDistribution, DomainName]
878981

879982
Outputs:
880983
DomainName:
@@ -902,7 +1005,7 @@ Outputs:
9021005
Description: Cloudfront Distribution ID
9031006
Value: !GetAtt AppFrontendCloudfrontDistribution.Id
9041007

905-
CloudfrontSecondaryDistributionId:
1008+
CloudfrontIcalDistributionId:
9061009
Description: Cloudfront Distribution ID
9071010
Value: !GetAtt AppIcalCloudfrontDistribution.Id
9081011

0 commit comments

Comments
 (0)