Skip to content

Commit 9b04f8f

Browse files
Fixes for CORS, enqueuing PRs, and storing user_id
Signed-off-by: Lukasz Gryglicki <lgryglicki@cncf.io> Assisted by [OpenAI](https://platform.openai.com/) Assisted by [GitHub Copilot](https://github.com/features/copilot)
1 parent 86c3d53 commit 9b04f8f

4 files changed

Lines changed: 79 additions & 17 deletions

File tree

cla-backend-legacy/internal/api/github_oauth.go

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,19 +425,39 @@ func (h *Handlers) githubSignRequest(w http.ResponseWriter, r *http.Request) {
425425
sessionSetString(sess, "github_installation_id", installationID)
426426
sessionSetString(sess, "github_repository_id", repoID)
427427
sessionSetString(sess, "github_change_request_id", changeID)
428-
429-
// Determine origin URL from PR.
430-
inst, _ := strconv.ParseInt(strings.TrimSpace(installationID), 10, 64)
431-
repo, _ := strconv.ParseInt(strings.TrimSpace(repoID), 10, 64)
432-
pr, _ := strconv.ParseInt(strings.TrimSpace(changeID), 10, 64)
433-
if inst > 0 && repo > 0 && pr > 0 {
434-
if origin, err := h.github.GetPullRequestHTMLURL(ctx, inst, repo, pr); err == nil {
435-
sessionSetString(sess, "github_origin_url", origin)
436-
} else {
437-
// Mirror Python: exceptions bubble up as server errors.
438-
respond.JSON(w, http.StatusInternalServerError, map[string]any{"errors": "unable to fetch pull request", "details": err.Error()})
439-
return
428+
// Determine origin URL from PR. Python parses all three path IDs as int()
429+
// before creating the GitHub PR URL/OAuth state; malformed IDs raise and
430+
// never proceed to OAuth. Keep that fail-fast behavior.
431+
inst, err := strconv.ParseInt(strings.TrimSpace(installationID), 10, 64)
432+
if err != nil || inst <= 0 {
433+
if err == nil {
434+
err = errors.New("installation_id must be a positive integer")
435+
}
436+
respond.JSON(w, http.StatusInternalServerError, map[string]any{"errors": "unable to fetch pull request", "details": err.Error()})
437+
return
438+
}
439+
repo, err := strconv.ParseInt(strings.TrimSpace(repoID), 10, 64)
440+
if err != nil || repo <= 0 {
441+
if err == nil {
442+
err = errors.New("github_repository_id must be a positive integer")
443+
}
444+
respond.JSON(w, http.StatusInternalServerError, map[string]any{"errors": "unable to fetch pull request", "details": err.Error()})
445+
return
446+
}
447+
pr, err := strconv.ParseInt(strings.TrimSpace(changeID), 10, 64)
448+
if err != nil || pr <= 0 {
449+
if err == nil {
450+
err = errors.New("change_request_id must be a positive integer")
440451
}
452+
respond.JSON(w, http.StatusInternalServerError, map[string]any{"errors": "unable to fetch pull request", "details": err.Error()})
453+
return
454+
}
455+
if origin, err := h.github.GetPullRequestHTMLURL(ctx, inst, repo, pr); err == nil {
456+
sessionSetString(sess, "github_origin_url", origin)
457+
} else {
458+
// Mirror Python: exceptions bubble up as server errors.
459+
respond.JSON(w, http.StatusInternalServerError, map[string]any{"errors": "unable to fetch pull request", "details": err.Error()})
460+
return
441461
}
442462

443463
if sessionGetMap(sess, "github_oauth2_token") != nil {

cla-backend-legacy/internal/api/handlers.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,7 @@ func (h *Handlers) handleLegacyGithubMergeGroup(ctx context.Context, payload map
13561356
func (h *Handlers) handleLegacyGithubReceivedActivity(ctx context.Context, payload map[string]any) error {
13571357
action := githubActivityAction(payload)
13581358
switch action {
1359-
case "opened", "reopened", "synchronize":
1359+
case "opened", "reopened", "synchronize", "enqueued":
13601360
return h.handleLegacyGithubPullRequestUpdate(ctx, payload)
13611361
case "checks_requested":
13621362
return h.handleLegacyGithubMergeGroup(ctx, payload)
@@ -3002,7 +3002,9 @@ func (h *Handlers) GetUserActiveSignatureV2(w http.ResponseWriter, r *http.Reque
30023002
respond.JSON(w, http.StatusOK, nil)
30033003
return
30043004
}
3005-
3005+
if metadataString(metadata, "user_id") == "" {
3006+
metadata["user_id"] = userID
3007+
}
30063008
returnURL, err := h.computeReturnURLFromActiveSignatureMetadata(r.Context(), metadata)
30073009
if err != nil {
30083010
respond.JSON(w, http.StatusInternalServerError, err.Error())

cla-backend-legacy/internal/middleware/cors.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,39 @@ func addAllowedOrigin(raw string) {
6161
func addContributorConsoleOrigins() {
6262
addAllowedOrigin(os.Getenv("CLA_CONTRIBUTOR_BASE"))
6363
addAllowedOrigin(os.Getenv("CLA_CONTRIBUTOR_V2_BASE"))
64+
addAllowedOrigin(os.Getenv("CLA_CORPORATE_BASE"))
65+
addAllowedOrigin(os.Getenv("CLA_CORPORATE_V2_BASE"))
66+
addAllowedOrigin(os.Getenv("CLA_LANDING_PAGE"))
67+
}
68+
69+
func addBuiltInEasyCLAOrigins() {
70+
// Keep known EasyCLA dev/staging/prod UI and API aliases available even when
71+
// ALLOWED_ORIGINS in SSM is incomplete. Credentialed browser requests cannot
72+
// use a wildcard Access-Control-Allow-Origin value.
73+
for _, origin := range []string{
74+
"https://easycla.dev.communitybridge.org",
75+
"https://easycla.staging.communitybridge.org",
76+
"https://easycla.communitybridge.org",
77+
"https://easycla.dev.platform.linuxfoundation.org",
78+
"https://easycla.staging.platform.linuxfoundation.org",
79+
"https://easycla.lfx.linuxfoundation.org",
80+
"https://contributor.easycla.lfx.linuxfoundation.org",
81+
"https://project.dev.lfcla.com",
82+
"https://project.v1.easycla.lfx.linuxfoundation.org",
83+
"https://corporate.dev.lfcla.com",
84+
"https://corporate.v1.easycla.lfx.linuxfoundation.org",
85+
"https://api.lfcla.dev.platform.linuxfoundation.org",
86+
"https://api.lfcla.staging.platform.linuxfoundation.org",
87+
"https://api.easycla.lfx.linuxfoundation.org",
88+
"https://api.dev.lfcla.com",
89+
"https://api.staging.lfcla.com",
90+
"https://api.lfcla.com",
91+
"https://api-gw.dev.platform.linuxfoundation.org",
92+
"https://api-gw.staging.platform.linuxfoundation.org",
93+
"https://api-gw.platform.linuxfoundation.org",
94+
} {
95+
addAllowedOrigin(origin)
96+
}
6497
}
6598

6699
func loadAllowedOriginsFromEnv() {
@@ -69,6 +102,7 @@ func loadAllowedOriginsFromEnv() {
69102
// Backwards compatible default: allow all.
70103
allowAllOrigins = true
71104
addContributorConsoleOrigins()
105+
addBuiltInEasyCLAOrigins()
72106
return
73107
}
74108

@@ -83,6 +117,7 @@ func loadAllowedOriginsFromEnv() {
83117
addAllowedOrigin(v)
84118
}
85119
addContributorConsoleOrigins()
120+
addBuiltInEasyCLAOrigins()
86121
if len(allowedOrigins) == 0 && !allowAllOrigins {
87122
allowAllOrigins = true
88123
}
@@ -106,6 +141,7 @@ func loadAllowedOriginsFromEnv() {
106141
// Therefore these origins must be allowed to call the v1/v2 APIs after
107142
// GitHub OAuth redirects back to EasyCLA.
108143
addContributorConsoleOrigins()
144+
addBuiltInEasyCLAOrigins()
109145

110146
if len(allowedOrigins) == 0 && !allowAllOrigins {
111147
allowAllOrigins = true
@@ -148,7 +184,8 @@ func CORS(next http.Handler) http.Handler {
148184

149185
// Legacy Python sets the string literal "true".
150186
w.Header().Set("Access-Control-Allow-Credentials", "true")
151-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
187+
// w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
188+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Hub-Signature, X-Hub-Signature-256, X-GitHub-Event, X-GitHub-Delivery")
152189
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
153190

154191
if r.Method == http.MethodOptions {

cla-backend/serverless.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ functions:
544544
- http:
545545
method: ANY
546546
path: v1/{proxy+}
547-
cors: true
547+
# cors: true
548548
package:
549549
individually: true
550550
patterns:
@@ -562,7 +562,7 @@ functions:
562562
- http:
563563
method: ANY
564564
path: v2/{proxy+}
565-
cors: true
565+
# cors: true
566566
package:
567567
individually: true
568568
patterns:
@@ -635,6 +635,9 @@ functions:
635635
- http:
636636
method: POST
637637
path: v2/github/activity
638+
- http:
639+
method: OPTIONS
640+
path: v2/github/activity
638641
package:
639642
individually: true
640643
patterns:

0 commit comments

Comments
 (0)