From 59a97538d575495ff548c5c219a6880d05e7ac06 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 10 Oct 2023 12:00:06 +0400 Subject: [PATCH] chore: refactor ExtractUserParam to call function --- coderd/httpmw/userparam.go | 132 ++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/coderd/httpmw/userparam.go b/coderd/httpmw/userparam.go index de3446d69cdaf..bfa0106004caf 100644 --- a/coderd/httpmw/userparam.go +++ b/coderd/httpmw/userparam.go @@ -39,73 +39,83 @@ func UserParam(r *http.Request) database.User { func ExtractUserParam(db database.Store, redirectToLoginOnMe bool) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - var ( - ctx = r.Context() - user database.User - err error - ) - - // userQuery is either a uuid, a username, or 'me' - userQuery := chi.URLParam(r, "user") - if userQuery == "" { - httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "\"user\" must be provided.", - }) + ctx := r.Context() + user, ok := extractUserContext(ctx, db, rw, r, redirectToLoginOnMe) + if !ok { + // response already handled return } + ctx = context.WithValue(ctx, userParamContextKey{}, user) + next.ServeHTTP(rw, r.WithContext(ctx)) + }) + } +} - if userQuery == "me" { - apiKey, ok := APIKeyOptional(r) - if !ok { - if redirectToLoginOnMe { - RedirectToLogin(rw, r, nil, SignedOutErrorMessage) - return - } +// extractUserContext queries the database for the parameterized `{user}` from the request URL. +// +//nolint:revive +func extractUserContext(ctx context.Context, db database.Store, rw http.ResponseWriter, r *http.Request, redirectToLoginOnMe bool) (user database.User, ok bool) { + // userQuery is either a uuid, a username, or 'me' + userQuery := chi.URLParam(r, "user") + if userQuery == "" { + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: "\"user\" must be provided.", + }) + return database.User{}, true + } - httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Cannot use \"me\" without a valid session.", - }) - return - } - //nolint:gocritic // System needs to be able to get user from param. - user, err = db.GetUserByID(dbauthz.AsSystemRestricted(ctx), apiKey.UserID) - if httpapi.Is404Error(err) { - httpapi.ResourceNotFound(rw) - return - } - if err != nil { - httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching user.", - Detail: err.Error(), - }) - return - } - } else if userID, err := uuid.Parse(userQuery); err == nil { - //nolint:gocritic // If the userQuery is a valid uuid - user, err = db.GetUserByID(dbauthz.AsSystemRestricted(ctx), userID) - if err != nil { - httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: userErrorMessage, - Detail: fmt.Sprintf("queried user=%q", userQuery), - }) - return - } - } else { - // nolint:gocritic // Try as a username last - user, err = db.GetUserByEmailOrUsername(dbauthz.AsSystemRestricted(ctx), database.GetUserByEmailOrUsernameParams{ - Username: userQuery, - }) - if err != nil { - httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: userErrorMessage, - Detail: fmt.Sprintf("queried user=%q", userQuery), - }) - return - } + if userQuery == "me" { + apiKey, ok := APIKeyOptional(r) + if !ok { + if redirectToLoginOnMe { + RedirectToLogin(rw, r, nil, SignedOutErrorMessage) + return database.User{}, false } - ctx = context.WithValue(ctx, userParamContextKey{}, user) - next.ServeHTTP(rw, r.WithContext(ctx)) + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: "Cannot use \"me\" without a valid session.", + }) + return database.User{}, false + } + //nolint:gocritic // System needs to be able to get user from param. + user, err := db.GetUserByID(dbauthz.AsSystemRestricted(ctx), apiKey.UserID) + if httpapi.Is404Error(err) { + httpapi.ResourceNotFound(rw) + return database.User{}, false + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error fetching user.", + Detail: err.Error(), + }) + return database.User{}, false + } + return user, true + } + + if userID, err := uuid.Parse(userQuery); err == nil { + //nolint:gocritic // If the userQuery is a valid uuid + user, err = db.GetUserByID(dbauthz.AsSystemRestricted(ctx), userID) + if err != nil { + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: userErrorMessage, + Detail: fmt.Sprintf("queried user=%q", userQuery), + }) + return database.User{}, false + } + return user, true + } + + // nolint:gocritic // Try as a username last + user, err := db.GetUserByEmailOrUsername(dbauthz.AsSystemRestricted(ctx), database.GetUserByEmailOrUsernameParams{ + Username: userQuery, + }) + if err != nil { + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: userErrorMessage, + Detail: fmt.Sprintf("queried user=%q", userQuery), }) + return database.User{}, false } + return user, true }