mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
fix: Show error message from backend on create existing user (#1964)
* Show error message from backend on create existing user * Format
This commit is contained in:
@@ -33,6 +33,14 @@ export const isApiError = (err: any): err is ApiError => {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* ApiErrors contain useful error messages in their response body. They contain an overall message
|
||||
* and may also contain errors for specific form fields.
|
||||
* @param error ApiError
|
||||
* @returns true if the ApiError contains error messages for specific form fields.
|
||||
*/
|
||||
export const hasApiFieldErrors = (error: ApiError): boolean => Array.isArray(error.response.data.errors)
|
||||
|
||||
export const mapApiErrorToFieldErrors = (apiErrorResponse: ApiErrorResponse): FieldErrors => {
|
||||
const result: FieldErrors = {}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Language as FooterLanguage } from "../../../components/FormFooter/FormF
|
||||
import { history, render } from "../../../testHelpers/renderHelpers"
|
||||
import { server } from "../../../testHelpers/server"
|
||||
import { Language as UserLanguage } from "../../../xServices/users/usersXService"
|
||||
import { CreateUserPage, Language } from "./CreateUserPage"
|
||||
import { CreateUserPage } from "./CreateUserPage"
|
||||
|
||||
const fillForm = async ({
|
||||
username = "someuser",
|
||||
@@ -46,7 +46,7 @@ describe("Create User Page", () => {
|
||||
})
|
||||
render(<CreateUserPage />)
|
||||
await fillForm({})
|
||||
const errorMessage = await screen.findByText(Language.unknownError)
|
||||
const errorMessage = await screen.findByText(UserLanguage.createUserError)
|
||||
expect(errorMessage).toBeDefined()
|
||||
})
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ export const CreateUserPage: React.FC = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const myOrgId = useSelector(xServices.authXService, selectOrgId)
|
||||
const [usersState, usersSend] = useActor(xServices.usersXService)
|
||||
const { createUserError, createUserFormErrors } = usersState.context
|
||||
const { createUserErrorMessage, createUserFormErrors } = usersState.context
|
||||
const navigate = useNavigate()
|
||||
// There is no field for organization id in Community Edition, so handle its field error like a generic error
|
||||
const genericError =
|
||||
createUserError || createUserFormErrors?.organization_id || !myOrgId ? Language.unknownError : undefined
|
||||
createUserErrorMessage || createUserFormErrors?.organization_id || (!myOrgId ? Language.unknownError : undefined)
|
||||
|
||||
return (
|
||||
<Margins>
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
import { assign, createMachine } from "xstate"
|
||||
import * as API from "../../api/api"
|
||||
import { ApiError, FieldErrors, getErrorMessage, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
|
||||
import {
|
||||
ApiError,
|
||||
FieldErrors,
|
||||
getErrorMessage,
|
||||
hasApiFieldErrors,
|
||||
isApiError,
|
||||
mapApiErrorToFieldErrors,
|
||||
} from "../../api/errors"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { displayError, displaySuccess } from "../../components/GlobalSnackbar/utils"
|
||||
import { generateRandomString } from "../../util/random"
|
||||
|
||||
export const Language = {
|
||||
createUserSuccess: "Successfully created user.",
|
||||
createUserError: "Error on creating the user.",
|
||||
suspendUserSuccess: "Successfully suspended the user.",
|
||||
suspendUserError: "Error on suspend the user.",
|
||||
suspendUserError: "Error on suspending the user.",
|
||||
resetUserPasswordSuccess: "Successfully updated the user password.",
|
||||
resetUserPasswordError: "Error on reset the user password.",
|
||||
resetUserPasswordError: "Error on resetting the user password.",
|
||||
updateUserRolesSuccess: "Successfully updated the user roles.",
|
||||
updateUserRolesError: "Error on update the user roles.",
|
||||
updateUserRolesError: "Error on updating the user roles.",
|
||||
}
|
||||
|
||||
export interface UsersContext {
|
||||
// Get users
|
||||
users?: TypesGen.User[]
|
||||
getUsersError?: Error | unknown
|
||||
createUserError?: Error | unknown
|
||||
createUserErrorMessage?: string
|
||||
createUserFormErrors?: FieldErrors
|
||||
// Suspend user
|
||||
userIdToSuspend?: TypesGen.User["id"]
|
||||
@@ -122,7 +130,7 @@ export const usersMachine = createMachine(
|
||||
onError: [
|
||||
{
|
||||
target: "idle",
|
||||
cond: "isFormError",
|
||||
cond: "hasFieldErrors",
|
||||
actions: ["assignCreateUserFormErrors"],
|
||||
},
|
||||
{
|
||||
@@ -235,7 +243,7 @@ export const usersMachine = createMachine(
|
||||
},
|
||||
},
|
||||
guards: {
|
||||
isFormError: (_, event) => isApiError(event.data),
|
||||
hasFieldErrors: (_, event) => isApiError(event.data) && hasApiFieldErrors(event.data),
|
||||
},
|
||||
actions: {
|
||||
assignUsers: assign({
|
||||
@@ -258,7 +266,7 @@ export const usersMachine = createMachine(
|
||||
getUsersError: undefined,
|
||||
})),
|
||||
assignCreateUserError: assign({
|
||||
createUserError: (_, event) => event.data,
|
||||
createUserErrorMessage: (_, event) => getErrorMessage(event.data, Language.createUserError),
|
||||
}),
|
||||
assignCreateUserFormErrors: assign({
|
||||
// the guard ensures it is ApiError
|
||||
|
||||
Reference in New Issue
Block a user