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,
renderWithAuth,
} from "../../../testHelpers/renderHelpers"
import { Language as authXServiceLanguage } from "../../../xServices/auth/authXService"
import { Language as SSHKeysPageLanguage, SSHKeysPage } from "./SSHKeysPage"
import { Language as SSHKeysPageViewLanguage } from "./SSHKeysPageView"
import { i18n } from "i18n"
const { t } = i18n
describe("SSH keys Page", () => {
it("shows the SSH key", async () => {
@ -52,7 +54,10 @@ describe("SSH keys Page", () => {
fireEvent.click(confirmButton)
// 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
expect(API.regenerateUserSSHKey).toBeCalledTimes(1)

View File

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

View File

@ -5,7 +5,6 @@ import { displaySuccess } from "../../components/GlobalSnackbar/utils"
export const Language = {
successProfileUpdate: "Updated settings.",
successRegenerateSSHKey: "SSH Key regenerated successfully",
}
export const checks = {
@ -83,20 +82,12 @@ export interface AuthContext {
methods?: TypesGen.AuthMethods
permissions?: Permissions
checkPermissionsError?: Error | unknown
// SSH
sshKey?: TypesGen.GitSSHKey
getSSHKeyError?: Error | unknown
regenerateSSHKeyError?: Error | unknown
}
export type AuthEvent =
| { type: "SIGN_OUT" }
| { type: "SIGN_IN"; email: string; password: string }
| { 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" }
export const authMachine =
@ -128,12 +119,6 @@ export const authMachine =
checkPermissions: {
data: TypesGen.AuthorizationResponse
}
getSSHKey: {
data: TypesGen.GitSSHKey
}
regenerateSSHKey: {
data: TypesGen.GitSSHKey
}
hasFirstUser: {
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: {
initial: "idle",
states: {
@ -480,9 +392,6 @@ export const authMachine =
checks: permissionsToCheck,
})
},
// SSH
getSSHKey: () => API.getUserSSHKey(),
regenerateSSHKey: () => API.regenerateUserSSHKey(),
// First user
hasFirstUser: () => API.hasFirstUser(),
},
@ -538,25 +447,6 @@ export const authMachine =
clearGetPermissionsError: assign({
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 }) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- data can be undefined
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" }),
)
},
},
},
)