Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: handlegetUser error#3285

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

Merged
AbhineetJain merged 6 commits intomainfromabhineetjain/handle-get-user-error
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletionscoderd/httpmw/apikey.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,6 +51,11 @@ type OAuth2Configs struct {
Github OAuth2Config
}

const (
signedOutErrorMessage string = "You are signed out or your session has expired. Please sign in again to continue."
internalErrorMessage string = "An internal error occurred. Please try again or contact the system administrator."
)

// ExtractAPIKey requires authentication using a valid API key.
// It handles extending an API key if it comes close to expiry,
// updating the last used time in the database.
Expand DownExpand Up@@ -83,15 +88,17 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
}
if cookieValue == "" {
write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Cookie %q or query parameter must be provided.", codersdk.SessionTokenKey),
Message: signedOutErrorMessage,
Detail: fmt.Sprintf("Cookie %q or query parameter must be provided.", codersdk.SessionTokenKey),
})
return
}
parts := strings.Split(cookieValue, "-")
// APIKeys are formatted: ID-SECRET
if len(parts) != 2 {
write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key format.", codersdk.SessionTokenKey),
Message: signedOutErrorMessage,
Detail: fmt.Sprintf("Invalid %q cookie API key format.", codersdk.SessionTokenKey),
})
return
}
Expand All@@ -100,27 +107,30 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Ensuring key lengths are valid.
if len(keyID) != 10 {
write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key id.", codersdk.SessionTokenKey),
Message: signedOutErrorMessage,
Detail: fmt.Sprintf("Invalid %q cookie API key id.", codersdk.SessionTokenKey),
})
return
}
if len(keySecret) != 22 {
write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key secret.", codersdk.SessionTokenKey),
Message: signedOutErrorMessage,
Detail: fmt.Sprintf("Invalid %q cookie API key secret.", codersdk.SessionTokenKey),
})
return
}
key, err := db.GetAPIKeyByID(r.Context(), keyID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
write(http.StatusUnauthorized, codersdk.Response{
Message: "API key is invalid.",
Message: signedOutErrorMessage,
Detail: "API key is invalid.",
})
return
}
write(http.StatusInternalServerError, codersdk.Response{
Message:"Internal error fetching API key by id.",
Detail: err.Error(),
Message:internalErrorMessage,
Detail:fmt.Sprintf("Internal error fetching API key by id. %s",err.Error()),
})
return
}
Expand All@@ -129,7 +139,8 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Checking to see if the secret is valid.
if subtle.ConstantTimeCompare(key.HashedSecret, hashed[:]) != 1 {
write(http.StatusUnauthorized, codersdk.Response{
Message: "API key secret is invalid.",
Message: signedOutErrorMessage,
Detail: "API key secret is invalid.",
})
return
}
Expand All@@ -146,7 +157,8 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
oauthConfig = oauth.Github
default:
write(http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Unexpected authentication type %q.", key.LoginType),
Message: internalErrorMessage,
Detail: fmt.Sprintf("Unexpected authentication type %q.", key.LoginType),
})
return
}
Expand DownExpand Up@@ -174,7 +186,8 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Checking if the key is expired.
if key.ExpiresAt.Before(now) {
write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("API key expired at %q.", key.ExpiresAt.String()),
Message: signedOutErrorMessage,
Detail: fmt.Sprintf("API key expired at %q.", key.ExpiresAt.String()),
})
return
}
Expand DownExpand Up@@ -216,7 +229,8 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
})
if err != nil {
write(http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("API key couldn't update: %s.", err.Error()),
Message: internalErrorMessage,
Detail: fmt.Sprintf("API key couldn't update: %s.", err.Error()),
})
return
}
Expand All@@ -228,8 +242,8 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
roles, err := db.GetAuthorizationUserRoles(r.Context(), key.UserID)
if err != nil {
write(http.StatusUnauthorized, codersdk.Response{
Message:"Internal error fetching user's roles.",
Detail: err.Error(),
Message:internalErrorMessage,
Detail:fmt.Sprintf("Internal error fetching user's roles. %s",err.Error()),
})
return
}
Expand Down
5 changes: 3 additions & 2 deletionssite/src/components/RequireAuth/RequireAuth.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,10 @@ export const RequireAuth: React.FC<RequireAuthProps> = ({ children }) => {
const xServices = useContext(XServiceContext)
const [authState] = useActor(xServices.authXService)
const location = useLocation()
const navigateTo = location.pathname === "/" ? "/login" : embedRedirect(location.pathname)
const isHomePage = location.pathname === "/"
const navigateTo = isHomePage ? "/login" : embedRedirect(location.pathname)
if (authState.matches("signedOut")) {
return <Navigate to={navigateTo} />
return <Navigate to={navigateTo}state={{ isRedirect: !isHomePage }}/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

doesisRedirect replicate the functionality ofembedRedirect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think wecould use one both to know whether to show the error and where to go next, but it might be better to keep them separate like this

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yeah, we’d probably have to retrieve the redirect in the component but that didn’t seem like a very solid approach.

} else if (authState.hasTag("loading")) {
return <FullScreenLoader />
} else {
Expand Down
23 changes: 23 additions & 0 deletionssite/src/components/SignInForm/SignInForm.stories.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,6 +51,17 @@ WithLoginError.args = {
},
}

export const WithGetUserError = Template.bind({})
WithGetUserError.args = {
...SignedOut.args,
loginErrors: {
[LoginErrors.GET_USER_ERROR]: makeMockApiError({
message: "You are logged out. Please log in to continue.",
detail: "API Key is invalid.",
}),
},
}

export const WithCheckPermissionsError = Template.bind({})
WithCheckPermissionsError.args = {
...SignedOut.args,
Expand All@@ -70,6 +81,18 @@ WithAuthMethodsError.args = {
},
}

export const WithGetUserAndAuthMethodsError = Template.bind({})
WithGetUserAndAuthMethodsError.args = {
...SignedOut.args,
loginErrors: {
[LoginErrors.GET_USER_ERROR]: makeMockApiError({
message: "You are logged out. Please log in to continue.",
detail: "API Key is invalid.",
}),
[LoginErrors.GET_METHODS_ERROR]: new Error("Failed to fetch auth methods"),
},
}

export const WithGithub = Template.bind({})
WithGithub.args = {
...SignedOut.args,
Expand Down
2 changes: 2 additions & 0 deletionssite/src/components/SignInForm/SignInForm.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,7 @@ interface BuiltInAuthFormValues {

export enum LoginErrors {
AUTH_ERROR = "authError",
GET_USER_ERROR = "getUserError",
CHECK_PERMISSIONS_ERROR = "checkPermissionsError",
GET_METHODS_ERROR = "getMethodsError",
}
Expand All@@ -36,6 +37,7 @@ export const Language = {
emailRequired: "Please enter an email address.",
errorMessages: {
[LoginErrors.AUTH_ERROR]: "Incorrect email or password.",
[LoginErrors.GET_USER_ERROR]: "Failed to fetch user details.",
[LoginErrors.CHECK_PERMISSIONS_ERROR]: "Unable to fetch user permissions.",
[LoginErrors.GET_METHODS_ERROR]: "Unable to fetch auth methods.",
},
Expand Down
17 changes: 12 additions & 5 deletionssite/src/pages/LoginPage/LoginPage.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,7 @@ import React, { useContext } from "react"
import { Helmet } from "react-helmet"
import { Navigate, useLocation } from "react-router-dom"
import { Footer } from "../../components/Footer/Footer"
import { SignInForm } from "../../components/SignInForm/SignInForm"
import {LoginErrors,SignInForm } from "../../components/SignInForm/SignInForm"
import { pageTitle } from "../../util/page"
import { retrieveRedirect } from "../../util/redirect"
import { XServiceContext } from "../../xServices/StateContext"
Expand All@@ -28,19 +28,25 @@ export const useStyles = makeStyles((theme) => ({
},
}))

interface LocationState {
isRedirect: boolean
}

export const LoginPage: React.FC = () => {
const styles = useStyles()
const location = useLocation()
const xServices = useContext(XServiceContext)
const [authState, authSend] = useActor(xServices.authXService)
const isLoading = authState.hasTag("loading")
const redirectTo = retrieveRedirect(location.search)
const locationState = location.state ? (location.state as LocationState) : null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Do we need to use a ternary because of types? Or can we:

Suggested change
constlocationState=location.state ?(location.stateasLocationState) :null
constlocationState=location.state??null

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

location.state can benull, but since we are typecasting it, the compiler thinks it is nevernull, so we are typecasting it only if it is not null.

Kira-Pilot reacted with thumbs up emoji
const isRedirected = locationState ? locationState.isRedirect : false

const onSubmit = async ({ email, password }: { email: string; password: string }) => {
authSend({ type: "SIGN_IN", email, password })
}

const { authError, checkPermissionsError, getMethodsError } = authState.context
const { authError,getUserError,checkPermissionsError, getMethodsError } = authState.context

if (authState.matches("signedIn")) {
return <Navigate to={redirectTo} replace />
Expand All@@ -57,9 +63,10 @@ export const LoginPage: React.FC = () => {
redirectTo={redirectTo}
isLoading={isLoading}
loginErrors={{
authError,
checkPermissionsError,
getMethodsError,
[LoginErrors.AUTH_ERROR]: authError,
[LoginErrors.GET_USER_ERROR]: isRedirected ? getUserError : null,
[LoginErrors.CHECK_PERMISSIONS_ERROR]: checkPermissionsError,
[LoginErrors.GET_METHODS_ERROR]: getMethodsError,
}}
onSubmit={onSubmit}
/>
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp