- Notifications
You must be signed in to change notification settings - Fork928
feat: Allow using username in user queries#1221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -14,6 +14,13 @@ import ( | ||
type userParamContextKey struct{} | ||
const ( | ||
// userErrorMessage is a constant so that no information about the state | ||
// of the queried user can be gained. We return the same error if the user | ||
// does not exist, or if the input is just garbage. | ||
userErrorMessage = "\"user\" must be an existing uuid or username" | ||
) | ||
// UserParam returns the user from the ExtractUserParam handler. | ||
func UserParam(r *http.Request) database.User { | ||
user, ok := r.Context().Value(userParamContextKey{}).(database.User) | ||
@@ -27,32 +34,56 @@ func UserParam(r *http.Request) database.User { | ||
func ExtractUserParam(db database.Store) func(http.Handler) http.Handler { | ||
return func(next http.Handler) http.Handler { | ||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { | ||
var user database.User | ||
var err error | ||
// userQuery is either a uuid, a username, or 'me' | ||
userQuery := chi.URLParam(r, "user") | ||
if userQuery == "" { | ||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ | ||
Message: "\"user\" must be provided", | ||
}) | ||
return | ||
} | ||
if userQuery == "me" { | ||
user, err = db.GetUserByID(r.Context(), APIKey(r).UserID) | ||
if err != nil { | ||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ | ||
Message: fmt.Sprintf("get user: %s", err.Error()), | ||
}) | ||
return | ||
} | ||
} else if userID, err := uuid.Parse(userQuery); err == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. It might reduce complexity if we just disallow getting by UUID entirely. I'm not sure it provides a ton of value anyways, because you need to get the user to get the ID. You could of course list users to do that, but then just use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I'm not inclined to drop the functionality because usernamesmight be able to be changed. UUIDs never will. It's really nice to have a ID, as you can assume that will be constant no matter what. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Fair enough fair enough | ||
// If the userQuery is a valid uuid | ||
user, err = db.GetUserByID(r.Context(), userID) | ||
if err != nil { | ||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ | ||
Message: userErrorMessage, | ||
}) | ||
return | ||
} | ||
} else { | ||
// Try as a username last | ||
user, err = db.GetUserByEmailOrUsername(r.Context(), database.GetUserByEmailOrUsernameParams{ | ||
Username: userQuery, | ||
}) | ||
if err != nil { | ||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ | ||
Message: userErrorMessage, | ||
}) | ||
return | ||
} | ||
} | ||
apiKey := APIKey(r) | ||
if apiKey.UserID !=user.ID { | ||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ | ||
Message: "getting non-personal users isn't supported yet", | ||
}) | ||
return | ||
} | ||
ctx := context.WithValue(r.Context(), userParamContextKey{}, user) | ||
next.ServeHTTP(rw, r.WithContext(ctx)) | ||
}) | ||