refactor: Extract ssh logic from auth service (#5670)

* refactor: Extract ssh logic from auth service

* Update site/src/i18n/en/userSettingsPage.json

Co-authored-by: Kira Pilot <kira@coder.com>

Co-authored-by: Kira Pilot <kira@coder.com>
This commit is contained in:
Bruno Quaresma
2023-01-11 14:04:42 -03:00
committed by GitHub
parent 8e4af79cb2
commit a5d39adf3e
5 changed files with 146 additions and 133 deletions

View File

@ -1,3 +1,4 @@
{ {
"securityUpdateSuccessMessage": "Updated password." "securityUpdateSuccessMessage": "Updated password.",
"sshRegenerateSuccessMessage": "SSH Key regenerated successfully."
} }

View File

@ -5,9 +5,11 @@ import {
MockGitSSHKey, MockGitSSHKey,
renderWithAuth, renderWithAuth,
} from "../../../testHelpers/renderHelpers" } from "../../../testHelpers/renderHelpers"
import { Language as authXServiceLanguage } from "../../../xServices/auth/authXService"
import { Language as SSHKeysPageLanguage, SSHKeysPage } from "./SSHKeysPage" import { Language as SSHKeysPageLanguage, SSHKeysPage } from "./SSHKeysPage"
import { Language as SSHKeysPageViewLanguage } from "./SSHKeysPageView" import { Language as SSHKeysPageViewLanguage } from "./SSHKeysPageView"
import { i18n } from "i18n"
const { t } = i18n
describe("SSH keys Page", () => { describe("SSH keys Page", () => {
it("shows the SSH key", async () => { it("shows the SSH key", async () => {
@ -52,7 +54,10 @@ describe("SSH keys Page", () => {
fireEvent.click(confirmButton) fireEvent.click(confirmButton)
// Check if the success message is displayed // Check if the success message is displayed
await screen.findByText(authXServiceLanguage.successRegenerateSSHKey) const successMessage = t("sshRegenerateSuccessMessage", {
ns: "userSettingsPage",
})
await screen.findByText(successMessage)
// Check if the API was called correctly // Check if the API was called correctly
expect(API.regenerateUserSSHKey).toBeCalledTimes(1) expect(API.regenerateUserSSHKey).toBeCalledTimes(1)

View File

@ -1,8 +1,8 @@
import { useActor } from "@xstate/react" import { useMachine } from "@xstate/react"
import { useContext, useEffect, PropsWithChildren, FC } from "react" import { PropsWithChildren, FC } from "react"
import { sshKeyMachine } from "xServices/sshKey/sshKeyXService"
import { ConfirmDialog } from "../../../components/Dialogs/ConfirmDialog/ConfirmDialog" import { ConfirmDialog } from "../../../components/Dialogs/ConfirmDialog/ConfirmDialog"
import { Section } from "../../../components/SettingsLayout/Section" import { Section } from "../../../components/SettingsLayout/Section"
import { XServiceContext } from "../../../xServices/StateContext"
import { SSHKeysPageView } from "./SSHKeysPageView" import { SSHKeysPageView } from "./SSHKeysPageView"
export const Language = { export const Language = {
@ -15,19 +15,13 @@ export const Language = {
} }
export const SSHKeysPage: FC<PropsWithChildren<unknown>> = () => { export const SSHKeysPage: FC<PropsWithChildren<unknown>> = () => {
const xServices = useContext(XServiceContext) const [sshState, sshSend] = useMachine(sshKeyMachine)
const [authState, authSend] = useActor(xServices.authXService) const isLoading = sshState.matches("gettingSSHKey")
const { sshKey, getSSHKeyError, regenerateSSHKeyError } = authState.context const hasLoaded = sshState.matches("loaded")
const { getSSHKeyError, regenerateSSHKeyError, sshKey } = sshState.context
useEffect(() => {
authSend({ type: "GET_SSH_KEY" })
}, [authSend])
const isLoading = authState.matches("signedIn.ssh.gettingSSHKey")
const hasLoaded = authState.matches("signedIn.ssh.loaded")
const onRegenerateClick = () => { const onRegenerateClick = () => {
authSend({ type: "REGENERATE_SSH_KEY" }) sshSend({ type: "REGENERATE_SSH_KEY" })
} }
return ( return (
@ -46,17 +40,15 @@ export const SSHKeysPage: FC<PropsWithChildren<unknown>> = () => {
<ConfirmDialog <ConfirmDialog
type="delete" type="delete"
hideCancel={false} hideCancel={false}
open={authState.matches("signedIn.ssh.loaded.confirmSSHKeyRegenerate")} open={sshState.matches("confirmSSHKeyRegenerate")}
confirmLoading={authState.matches( confirmLoading={sshState.matches("regeneratingSSHKey")}
"signedIn.ssh.loaded.regeneratingSSHKey",
)}
title={Language.regenerateDialogTitle} title={Language.regenerateDialogTitle}
confirmText={Language.confirmLabel} confirmText={Language.confirmLabel}
onConfirm={() => { onConfirm={() => {
authSend({ type: "CONFIRM_REGENERATE_SSH_KEY" }) sshSend({ type: "CONFIRM_REGENERATE_SSH_KEY" })
}} }}
onClose={() => { onClose={() => {
authSend({ type: "CANCEL_REGENERATE_SSH_KEY" }) sshSend({ type: "CANCEL_REGENERATE_SSH_KEY" })
}} }}
description={<>{Language.regenerateDialogMessage}</>} description={<>{Language.regenerateDialogMessage}</>}
/> />

View File

@ -5,7 +5,6 @@ import { displaySuccess } from "../../components/GlobalSnackbar/utils"
export const Language = { export const Language = {
successProfileUpdate: "Updated settings.", successProfileUpdate: "Updated settings.",
successRegenerateSSHKey: "SSH Key regenerated successfully",
} }
export const checks = { export const checks = {
@ -83,20 +82,12 @@ export interface AuthContext {
methods?: TypesGen.AuthMethods methods?: TypesGen.AuthMethods
permissions?: Permissions permissions?: Permissions
checkPermissionsError?: Error | unknown checkPermissionsError?: Error | unknown
// SSH
sshKey?: TypesGen.GitSSHKey
getSSHKeyError?: Error | unknown
regenerateSSHKeyError?: Error | unknown
} }
export type AuthEvent = export type AuthEvent =
| { type: "SIGN_OUT" } | { type: "SIGN_OUT" }
| { type: "SIGN_IN"; email: string; password: string } | { type: "SIGN_IN"; email: string; password: string }
| { type: "UPDATE_PROFILE"; data: TypesGen.UpdateUserProfileRequest } | { type: "UPDATE_PROFILE"; data: TypesGen.UpdateUserProfileRequest }
| { type: "GET_SSH_KEY" }
| { type: "REGENERATE_SSH_KEY" }
| { type: "CONFIRM_REGENERATE_SSH_KEY" }
| { type: "CANCEL_REGENERATE_SSH_KEY" }
| { type: "GET_AUTH_METHODS" } | { type: "GET_AUTH_METHODS" }
export const authMachine = export const authMachine =
@ -128,12 +119,6 @@ export const authMachine =
checkPermissions: { checkPermissions: {
data: TypesGen.AuthorizationResponse data: TypesGen.AuthorizationResponse
} }
getSSHKey: {
data: TypesGen.GitSSHKey
}
regenerateSSHKey: {
data: TypesGen.GitSSHKey
}
hasFirstUser: { hasFirstUser: {
data: boolean data: boolean
} }
@ -279,79 +264,6 @@ export const authMachine =
}, },
}, },
}, },
ssh: {
initial: "idle",
states: {
idle: {
on: {
GET_SSH_KEY: {
target: "gettingSSHKey",
},
},
},
gettingSSHKey: {
entry: "clearGetSSHKeyError",
invoke: {
src: "getSSHKey",
onDone: [
{
actions: "assignSSHKey",
target: "loaded",
},
],
onError: [
{
actions: "assignGetSSHKeyError",
target: "idle",
},
],
},
},
loaded: {
initial: "idle",
states: {
idle: {
on: {
REGENERATE_SSH_KEY: {
target: "confirmSSHKeyRegenerate",
},
},
},
confirmSSHKeyRegenerate: {
on: {
CANCEL_REGENERATE_SSH_KEY: {
target: "idle",
},
CONFIRM_REGENERATE_SSH_KEY: {
target: "regeneratingSSHKey",
},
},
},
regeneratingSSHKey: {
entry: "clearRegenerateSSHKeyError",
invoke: {
src: "regenerateSSHKey",
onDone: [
{
actions: [
"assignSSHKey",
"notifySuccessSSHKeyRegenerated",
],
target: "idle",
},
],
onError: [
{
actions: "assignRegenerateSSHKeyError",
target: "idle",
},
],
},
},
},
},
},
},
methods: { methods: {
initial: "idle", initial: "idle",
states: { states: {
@ -480,9 +392,6 @@ export const authMachine =
checks: permissionsToCheck, checks: permissionsToCheck,
}) })
}, },
// SSH
getSSHKey: () => API.getUserSSHKey(),
regenerateSSHKey: () => API.regenerateUserSSHKey(),
// First user // First user
hasFirstUser: () => API.hasFirstUser(), hasFirstUser: () => API.hasFirstUser(),
}, },
@ -538,25 +447,6 @@ export const authMachine =
clearGetPermissionsError: assign({ clearGetPermissionsError: assign({
checkPermissionsError: (_) => undefined, checkPermissionsError: (_) => undefined,
}), }),
// SSH
assignSSHKey: assign({
sshKey: (_, event) => event.data,
}),
assignGetSSHKeyError: assign({
getSSHKeyError: (_, event) => event.data,
}),
clearGetSSHKeyError: assign({
getSSHKeyError: (_) => undefined,
}),
assignRegenerateSSHKeyError: assign({
regenerateSSHKeyError: (_, event) => event.data,
}),
clearRegenerateSSHKeyError: assign({
regenerateSSHKeyError: (_) => undefined,
}),
notifySuccessSSHKeyRegenerated: () => {
displaySuccess(Language.successRegenerateSSHKey)
},
redirect: (_, { data }) => { redirect: (_, { data }) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- data can be undefined // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- data can be undefined
if (!data) { if (!data) {

View File

@ -0,0 +1,125 @@
import { getUserSSHKey, regenerateUserSSHKey } from "api/api"
import { GitSSHKey } from "api/typesGenerated"
import { displaySuccess } from "components/GlobalSnackbar/utils"
import { createMachine, assign } from "xstate"
import { i18n } from "i18n"
const { t } = i18n
interface Context {
sshKey?: GitSSHKey
getSSHKeyError?: unknown
regenerateSSHKeyError?: unknown
}
type Events =
| { type: "REGENERATE_SSH_KEY" }
| { type: "CONFIRM_REGENERATE_SSH_KEY" }
| { type: "CANCEL_REGENERATE_SSH_KEY" }
export const sshKeyMachine = createMachine(
{
id: "sshKeyState",
predictableActionArguments: true,
schema: {
context: {} as Context,
events: {} as Events,
services: {} as {
getSSHKey: {
data: GitSSHKey
}
regenerateSSHKey: {
data: GitSSHKey
}
},
},
tsTypes: {} as import("./sshKeyXService.typegen").Typegen0,
initial: "gettingSSHKey",
states: {
gettingSSHKey: {
entry: "clearGetSSHKeyError",
invoke: {
src: "getSSHKey",
onDone: [
{
actions: "assignSSHKey",
target: "loaded",
},
],
onError: [
{
actions: "assignGetSSHKeyError",
target: "notLoaded",
},
],
},
},
notLoaded: {
type: "final",
},
loaded: {
on: {
REGENERATE_SSH_KEY: {
target: "confirmSSHKeyRegenerate",
},
},
},
confirmSSHKeyRegenerate: {
on: {
CANCEL_REGENERATE_SSH_KEY: {
target: "loaded",
},
CONFIRM_REGENERATE_SSH_KEY: {
target: "regeneratingSSHKey",
},
},
},
regeneratingSSHKey: {
entry: "clearRegenerateSSHKeyError",
invoke: {
src: "regenerateSSHKey",
onDone: [
{
actions: ["assignSSHKey", "notifySuccessSSHKeyRegenerated"],
target: "loaded",
},
],
onError: [
{
actions: "assignRegenerateSSHKeyError",
target: "loaded",
},
],
},
},
},
},
{
services: {
getSSHKey: () => getUserSSHKey(),
regenerateSSHKey: () => regenerateUserSSHKey(),
},
actions: {
assignSSHKey: assign({
sshKey: (_, { data }) => data,
}),
assignGetSSHKeyError: assign({
getSSHKeyError: (_, { data }) => data,
}),
clearGetSSHKeyError: assign({
getSSHKeyError: (_) => undefined,
}),
assignRegenerateSSHKeyError: assign({
regenerateSSHKeyError: (_, { data }) => data,
}),
clearRegenerateSSHKeyError: assign({
regenerateSSHKeyError: (_) => undefined,
}),
notifySuccessSSHKeyRegenerated: () => {
displaySuccess(
t("sshRegenerateSuccessMessage", { ns: "userSettingsPage" }),
)
},
},
},
)