Skip to content

Commit aadeb87

Browse files
AlexanderWangYhieunguyent12hugoliu-code
authored
feat: rate limiting email interest submissions (#107)
* feat: form autosaving, submission, and tweaks to form fields (#98) * feat: form autosaving, submission, and tweaks to form fields * feat: storage interface + r2 implementation * chore: added error boundary for application forms * chore: added success and error submission message and some optimizations * chore: added regex validation and invalid application state * chore: removed resume_url column * chore: removed useless env variables * chore: refactored application submission handlers, services and repository * chore: changed submission status for db, updated loading state and error response for submission * chore: minor changes and created migration to update `saved_at` column * chore: cleanup and small changes * chore: change save delay to 3 seconnds instead of 1 * chore: removed testing code * chore: added requested changes from alex * chore: refactor frontend * chore: ensure application is published * refactor(applications): move application open function to event service and shortened * fix(portal): upcoming and application past button states and card states * fix(roles): add applicant role AFTER submission * refactor(application): rewrote some response values for application json --------- Co-authored-by: AlexanderWangY <alexander.yisu.wang@outlook.com> * Rate limiting for /interest (#105) --------- Co-authored-by: Hieu Nguyen <76720778+hieunguyent12@users.noreply.github.com> Co-authored-by: Hugo Liu <98724522+hugoliu-code@users.noreply.github.com>
1 parent fab857d commit aadeb87

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1908
-794
lines changed

apps/api/.air.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ testdata_dir = "testdata"
99
exclude_regex = ["_test.go"]
1010
include_ext = ["go", "tpl", "tmpl", "html"]
1111
log = "build-errors.log"
12+
poll = true
1213

1314
[color]
1415
app = ""

apps/api/cmd/api/main.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/swamphacks/core/apps/api/internal/db/repository"
1515
"github.com/swamphacks/core/apps/api/internal/logger"
1616
"github.com/swamphacks/core/apps/api/internal/services"
17+
"github.com/swamphacks/core/apps/api/internal/storage"
1718
)
1819

1920
func main() {
@@ -49,21 +50,29 @@ func main() {
4950
// Create new middleware injectable
5051
mw := middleware.NewMiddleware(database, logger, cfg)
5152

53+
// Initialize storage clients
54+
r2Client, err := storage.NewR2Client(cfg.CF.AccountID, cfg.CF.AccessKeyId, cfg.CF.AccessKeySecret, logger)
55+
if err != nil {
56+
logger.Fatal().Err(err).Msg("Failed to create R2 client")
57+
}
58+
5259
// Injections into repositories
5360
userRepo := repository.NewUserRepository(database)
5461
accountRepo := repository.NewAccountRespository(database)
5562
sessionRepo := repository.NewSessionRepository(database)
5663
eventInterestRepo := repository.NewEventInterestRepository(database)
5764
eventRepo := repository.NewEventRespository(database)
65+
applicationRepo := repository.NewApplicationRepository(database)
5866

5967
// Injections into services
6068
authService := services.NewAuthService(userRepo, accountRepo, sessionRepo, txm, client, logger, &cfg.Auth)
6169
eventInterestService := services.NewEventInterestService(eventInterestRepo, logger)
6270
eventService := services.NewEventService(eventRepo, userRepo, logger)
6371
emailService := services.NewEmailService(taskQueueClient, logger)
72+
applicationService := services.NewApplicationService(applicationRepo, eventService, txm, r2Client, &cfg.CoreBuckets, logger)
6473

6574
// Injections into handlers
66-
apiHandlers := handlers.NewHandlers(authService, eventInterestService, eventService, emailService, cfg, logger)
75+
apiHandlers := handlers.NewHandlers(authService, eventInterestService, eventService, emailService, applicationService, cfg, logger)
6776

6877
api := api.NewAPI(&logger, apiHandlers, mw)
6978

apps/api/go.mod

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,43 @@ require (
1515
)
1616

1717
require (
18+
github.com/aws/aws-sdk-go-v2 v1.38.0 // indirect
19+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect
20+
github.com/aws/aws-sdk-go-v2/config v1.31.1 // indirect
21+
github.com/aws/aws-sdk-go-v2/credentials v1.18.5 // indirect
22+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3 // indirect
23+
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.18.5 // indirect
24+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect
25+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect
26+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
27+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 // indirect
28+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect
29+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 // indirect
30+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect
31+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 // indirect
32+
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 // indirect
33+
github.com/aws/aws-sdk-go-v2/service/sso v1.28.1 // indirect
34+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.1 // indirect
35+
github.com/aws/aws-sdk-go-v2/service/sts v1.37.1 // indirect
36+
github.com/aws/smithy-go v1.22.5 // indirect
1837
github.com/cespare/xxhash/v2 v2.2.0 // indirect
1938
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
2039
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
40+
github.com/go-chi/httprate v0.15.0 // indirect
2141
github.com/go-playground/locales v0.14.1 // indirect
2242
github.com/go-playground/universal-translator v0.18.1 // indirect
2343
github.com/jackc/pgpassfile v1.0.0 // indirect
2444
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
2545
github.com/jackc/puddle/v2 v2.2.2 // indirect
46+
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
2647
github.com/leodido/go-urn v1.4.0 // indirect
2748
github.com/mattn/go-colorable v0.1.13 // indirect
2849
github.com/mattn/go-isatty v0.0.19 // indirect
2950
github.com/redis/go-redis/v9 v9.7.0 // indirect
3051
github.com/robfig/cron/v3 v3.0.1 // indirect
3152
github.com/spf13/cast v1.7.0 // indirect
3253
github.com/stretchr/testify v1.10.0 // indirect
54+
github.com/zeebo/xxh3 v1.0.2 // indirect
3355
golang.org/x/crypto v0.38.0 // indirect
3456
golang.org/x/net v0.38.0 // indirect
3557
golang.org/x/sync v0.14.0 // indirect

apps/api/go.sum

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,41 @@
1+
github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU=
2+
github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg=
3+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg=
4+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg=
5+
github.com/aws/aws-sdk-go-v2/config v1.31.1 h1:PSQn4ObaQLaHl6qjs+XYH2pkxyHzZlk1GgQDrKlRJ7I=
6+
github.com/aws/aws-sdk-go-v2/config v1.31.1/go.mod h1:3UA8Gj+2nzpV8WBUF0b19onBfz0YMXDQyGEW0Ru1ntI=
7+
github.com/aws/aws-sdk-go-v2/credentials v1.18.5 h1:DATc1xnpHUV8VgvtnVQul+zuCwK6vz7gtkbKEUZcuNI=
8+
github.com/aws/aws-sdk-go-v2/credentials v1.18.5/go.mod h1:y7aigZzjm1jUZuCgOrlBng+VJrKkknY2Cl0JWxG7vHU=
9+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3 h1:GicIdnekoJsjq9wqnvyi2elW6CGMSYKhdozE7/Svh78=
10+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3/go.mod h1:R7BIi6WNC5mc1kfRM7XM/VHC3uRWkjc396sfabq4iOo=
11+
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.18.5 h1:WTNSeU/4f/vevwK7zwEEjlX27LPZB1IwyjVAh+Q74iQ=
12+
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.18.5/go.mod h1:O84Dxp02jFDHRDbziaCRqMbe12+o+qih3ZD6Dio+1v0=
13+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA=
14+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4=
15+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s=
16+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc=
17+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
18+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
19+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs=
20+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3/go.mod h1:b9F9tk2HdHpbf3xbN7rUZcfmJI26N6NcJu/8OsBFI/0=
21+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM=
22+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44=
23+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY=
24+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY=
25+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s=
26+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM=
27+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc=
28+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo=
29+
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y=
30+
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE=
31+
github.com/aws/aws-sdk-go-v2/service/sso v1.28.1 h1:YfsU8hHGvVT+c6Q8MUs8haDbFQajAImrB7yZ9XnPcBY=
32+
github.com/aws/aws-sdk-go-v2/service/sso v1.28.1/go.mod h1:iS5OmxEcN4QIPXARGhavH7S8kETNL11kym6jhoS7IUQ=
33+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.1 h1:b4REsk5C0hooowAPmV8fS2haHb+HCyb5FKSKOZRBBfU=
34+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.1/go.mod h1:59qHWaY5B+Rs7HGTuVGaC32m0rdpQ68N8QCN3khYiqs=
35+
github.com/aws/aws-sdk-go-v2/service/sts v1.37.1 h1:ssCHKyNJqTnqRH4Vlf+jI0brtGQYBvzWwnATsOMk1mk=
36+
github.com/aws/aws-sdk-go-v2/service/sts v1.37.1/go.mod h1:JdeBDPgpJfuS6rU/hNglmOigKhyEZtBmbraLE4GK1J8=
37+
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
38+
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
139
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
240
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
341
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@@ -20,6 +58,8 @@ github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
2058
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
2159
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
2260
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
61+
github.com/go-chi/httprate v0.15.0 h1:j54xcWV9KGmPf/X4H32/aTH+wBlrvxL7P+SdnRqxh5g=
62+
github.com/go-chi/httprate v0.15.0/go.mod h1:rzGHhVrsBn3IMLYDOZQsSU4fJNWcjui4fWKJcCId1R4=
2363
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
2464
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
2565
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -45,6 +85,8 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
4585
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
4686
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
4787
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
88+
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
89+
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
4890
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
4991
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
5092
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -75,6 +117,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
75117
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
76118
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
77119
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
120+
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
121+
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
78122
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
79123
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
80124
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=

apps/api/internal/api/api.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package api
22

33
import (
44
"net/http"
5+
"time"
56

67
"github.com/go-chi/chi/v5"
78
"github.com/go-chi/chi/v5/middleware"
89
"github.com/go-chi/cors"
10+
"github.com/go-chi/httprate"
911
"github.com/rs/zerolog"
1012
"github.com/rs/zerolog/log"
1113
"github.com/swamphacks/core/apps/api/internal/api/handlers"
@@ -80,13 +82,21 @@ func (api *API) setupRoutes(mw *mw.Middleware) {
8082
r.With(mw.Auth.RequireAuth, ensureSuperuser).Post("/", api.Handlers.Event.CreateEvent)
8183
r.With(mw.Auth.RequireAuth).Get("/", api.Handlers.Event.GetEvents)
8284
r.Route("/{eventId}", func(r chi.Router) {
85+
8386
r.With(mw.Auth.RequireAuth, ensureEventAdmin).Patch("/", api.Handlers.Event.UpdateEventById)
8487
r.With(mw.Auth.RequireAuth, ensureSuperuser).Delete("/", api.Handlers.Event.DeleteEventById)
8588
r.With(mw.Auth.RequireAuth, ensureEventAdmin).Get("/staff", api.Handlers.Event.GetEventStaffUsers)
8689
r.With(mw.Auth.RequireAuth, ensureEventAdmin).Post("/roles", api.Handlers.Event.AssignEventRole)
8790
r.With(mw.Auth.RequireAuth).Get("/role", api.Handlers.Event.GetEventRole)
8891
r.Get("/", api.Handlers.Event.GetEventByID)
89-
r.Post("/interest", api.Handlers.EventInterest.AddEmailToEvent)
92+
r.With(httprate.LimitByIP(5, time.Minute)).Post("/interest", api.Handlers.EventInterest.AddEmailToEvent)
93+
r.Route("/application", func(r chi.Router) {
94+
r.Use(mw.Auth.RequireAuth)
95+
96+
r.Get("/", api.Handlers.Application.GetApplicationByUserAndEventID)
97+
r.Post("/submit", api.Handlers.Application.SubmitApplication)
98+
r.Post("/save", api.Handlers.Application.SaveApplication)
99+
})
90100
})
91101
})
92102

0 commit comments

Comments
 (0)