diff --git a/Containers/RepoManage/RepoManage.module.css b/Containers/RepoManage/RepoManage.module.css index 8bc6d64..f56b1fc 100644 --- a/Containers/RepoManage/RepoManage.module.css +++ b/Containers/RepoManage/RepoManage.module.css @@ -26,6 +26,7 @@ .modale h2 { margin-top: 0; + color: #374151; } @keyframes append-animate { diff --git a/Containers/RepoManage/RepoManage.tsx b/Containers/RepoManage/RepoManage.tsx index 41a5811..fb17ae4 100644 --- a/Containers/RepoManage/RepoManage.tsx +++ b/Containers/RepoManage/RepoManage.tsx @@ -93,7 +93,7 @@ export default function RepoManage(props: RepoManageProps) { ); else { const errorMessage = await response.json(); - toast.error(`An error has occurred : ${errorMessage.message.stdout}`, toastOptions); + toast.error(`An error has occurred : ${errorMessage.message.stderr}`, toastOptions); router.replace('/'); console.log('Fail to delete'); } @@ -171,7 +171,7 @@ export default function RepoManage(props: RepoManageProps) { router.replace('/'); } else { const errorMessage = await response.json(); - toast.error(`An error has occurred : ${errorMessage.message.stdout}`, toastOptions); + toast.error(`An error has occurred : ${errorMessage.message.stderr}`, toastOptions); router.replace('/'); console.log(`Fail to ${props.mode}`); } @@ -208,7 +208,7 @@ export default function RepoManage(props: RepoManageProps) { router.replace('/'); } else { const errorMessage = await response.json(); - toast.error(`An error has occurred : ${errorMessage.message.stdout}`, toastOptions); + toast.error(`An error has occurred : ${errorMessage.message.stderr}`, toastOptions); router.replace('/'); console.log(`Fail to ${props.mode}`); } diff --git a/helpers/functions/apiResponse.ts b/helpers/functions/apiResponse.ts index d8169c0..2382f5c 100644 --- a/helpers/functions/apiResponse.ts +++ b/helpers/functions/apiResponse.ts @@ -1,7 +1,19 @@ import { NextApiResponse } from 'next'; -const getErrorMessage = (error: unknown): string => { +const getErrorMessage = (error: unknown): any => { if (error instanceof Error) { + const shellError = error as any; + + // Handle shell errors + if ('code' in shellError || 'stderr' in shellError || 'stdout' in shellError) { + return { + code: shellError.code ?? null, + cmd: shellError.cmd ?? null, + stderr: shellError.stderr ?? null, + stdout: shellError.stdout ?? null, + }; + } + return error.message; } diff --git a/helpers/shells/createRepo.sh b/helpers/shells/createRepo.sh index 1f14c78..d964417 100755 --- a/helpers/shells/createRepo.sh +++ b/helpers/shells/createRepo.sh @@ -32,7 +32,7 @@ authorized_keys="${home}/.ssh/authorized_keys" # Check args if [ "$1" == "" ] || [ "$2" == "" ] || ! [[ "$2" =~ ^[0-9]+$ ]] || [ "$3" != "true" ] && [ "$3" != "false" ]; then - echo -n "This shell takes 3 arguments : SSH Public Key, Quota in Go [e.g. : 10], Append only mode [true|false]" + echo -n "This shell takes 3 arguments : SSH Public Key, Quota in Go [e.g. : 10], Append only mode [true|false]" >&2 exit 1 fi @@ -41,25 +41,25 @@ fi pattern='(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?' if [[ ! "$1" =~ $pattern ]] then - echo -n "Invalid public SSH KEY format. Provide a key in OpenSSH format (rsa, ed25519, ed25519-sk)" + echo -n "Invalid public SSH KEY format. Provide a key in OpenSSH format (rsa, ed25519, ed25519-sk)" >&2 exit 2 fi ## Check if authorized_keys exists if [ ! -f "${authorized_keys}" ];then - echo -n "${authorized_keys} must be present" + echo -n "${authorized_keys} must be present" >&2 exit 5 fi # Check if SSH pub key is already present in authorized_keys if grep -q "$1" "$authorized_keys"; then - echo -n "SSH pub key already present in authorized_keys" + echo -n "SSH pub key already present in authorized_keys" >&2 exit 3 fi # Check if borgbackup is installed if ! [ -x "$(command -v borg)" ]; then - echo -n "You must install borgbackup package." + echo -n "You must install borgbackup package." >&2 exit 4 fi diff --git a/helpers/shells/deleteRepo.sh b/helpers/shells/deleteRepo.sh index 3ea26f4..fef7661 100755 --- a/helpers/shells/deleteRepo.sh +++ b/helpers/shells/deleteRepo.sh @@ -21,7 +21,7 @@ authorized_keys="${home}/.ssh/authorized_keys" # Check arg if [[ $# -ne 1 || $1 = "" ]]; then - echo -n "You must provide a repositoryName in argument." + echo -n "You must provide a repositoryName in argument." >&2 exit 1 fi @@ -29,7 +29,7 @@ fi # If we receive another pattern there is necessarily a problem. repositoryName=$1 if ! [[ "$repositoryName" =~ ^[a-f0-9]{8}$ ]]; then - echo "Invalid repository name. Must be an 8-character hex string." + echo "Invalid repository name. Must be an 8-character hex string." >&2 exit 2 fi diff --git a/helpers/shells/updateRepo.sh b/helpers/shells/updateRepo.sh index 909b966..7358507 100755 --- a/helpers/shells/updateRepo.sh +++ b/helpers/shells/updateRepo.sh @@ -17,7 +17,7 @@ fi # Check args if [ "$1" == "" ] || [ "$2" == "" ] || [ "$3" == "" ] || [ "$4" != "true" ] && [ "$4" != "false" ]; then - echo -n "This shell takes 4 args: [repositoryName] [new SSH pub key] [quota] [Append only mode [true|false]]" + echo -n "This shell takes 4 args: [repositoryName] [new SSH pub key] [quota] [Append only mode [true|false]]" >&2 exit 1 fi @@ -26,7 +26,7 @@ fi pattern='(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?' if [[ ! "$2" =~ $pattern ]] then - echo -n "Invalid public SSH KEY format. Provide a key in OpenSSH format (rsa, ed25519, ed25519-sk)" + echo -n "Invalid public SSH KEY format. Provide a key in OpenSSH format (rsa, ed25519, ed25519-sk)" >&2 exit 2 fi @@ -34,13 +34,13 @@ fi # If we receive another pattern there is necessarily a problem. repositoryName=$1 if ! [[ "$repositoryName" =~ ^[a-f0-9]{8}$ ]]; then - echo "Invalid repository name. Must be an 8-character hex string." + echo "Invalid repository name. Must be an 8-character hex string." >&2 exit 3 fi # Check if a line in authorized_keys contains repository_name if ! grep -q "command=\".*${repositoryName}.*\",restrict" "$home/.ssh/authorized_keys"; then - echo -n "No line containing $repositoryName found in authorized_keys" + echo -n "No line containing $repositoryName found in authorized_keys" >&2 exit 4 fi @@ -64,7 +64,7 @@ while IFS= read -r line; do fi done < "$home/.ssh/authorized_keys" if [ "$found" = true ]; then - echo -n "This SSH pub key is already present in authorized_keys on a different line." + echo -n "This SSH pub key is already present in authorized_keys on a different line." >&2 exit 5 fi diff --git a/pages/api/v1/repositories/[slug]/index.test.ts b/pages/api/v1/repositories/[slug]/index.test.ts index 28d8931..1a673fc 100644 --- a/pages/api/v1/repositories/[slug]/index.test.ts +++ b/pages/api/v1/repositories/[slug]/index.test.ts @@ -216,7 +216,7 @@ describe('Repository PATCH by repositoryName', () => { comment: 'Test repository', }, ]); - vi.mocked(ShellService.updateRepo).mockResolvedValue({ stderr: 'Error', stdout: '' }); + vi.mocked(ShellService.updateRepo).mockRejectedValue(new Error('Failed to update repository')); const { req, res } = createMocks({ method: 'PATCH', query: { slug: 'a43928f3' }, @@ -224,6 +224,11 @@ describe('Repository PATCH by repositoryName', () => { }); await handler(req, res); expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'Failed to update repository', + }); + expect(ConfigService.updateRepoList).not.toHaveBeenCalled(); }); it('should successfully update repository with a session', async () => { @@ -444,12 +449,12 @@ describe('Repository DELETE by repositoryName', () => { comment: 'Test repository', }, ]); - vi.mocked(ShellService.deleteRepo).mockResolvedValue({ stderr: 'Error', stdout: '' }); + vi.mocked(ShellService.deleteRepo).mockRejectedValue(new Error('Failed to delete repository')); await handler(req, res); expect(res._getStatusCode()).toBe(500); expect(res._getJSONData()).toEqual({ status: 500, - message: 'API error, contact the administrator', + message: 'Failed to delete repository', }); expect(ConfigService.updateRepoList).not.toHaveBeenCalled(); }); diff --git a/pages/api/v1/repositories/[slug]/index.ts b/pages/api/v1/repositories/[slug]/index.ts index d4f693b..283ac86 100644 --- a/pages/api/v1/repositories/[slug]/index.ts +++ b/pages/api/v1/repositories/[slug]/index.ts @@ -106,16 +106,12 @@ export default async function handler( appendOnlyMode: appendOnlyMode ?? repo.appendOnlyMode, }; - const { stderr } = await ShellService.updateRepo( + await ShellService.updateRepo( updatedRepo.repositoryName, updatedRepo.sshPublicKey, updatedRepo.storageSize, updatedRepo.appendOnlyMode ?? false ); - if (stderr) { - console.log('Update repository error: ', stderr); - throw new Error(); - } const updatedRepoList = [...filteredRepoList, updatedRepo]; await ConfigService.updateRepoList(updatedRepoList, true); @@ -154,12 +150,7 @@ export default async function handler( return ApiResponse.notFound(res, 'Repository with name ' + slug + ' not found'); } - const { stderr } = await ShellService.deleteRepo(repoList[indexToDelete].repositoryName); - - if (stderr) { - console.log('Delete repository error: ', stderr); - return ApiResponse.serverError(res, undefined, 'Error deleting repository'); - } + await ShellService.deleteRepo(repoList[indexToDelete].repositoryName); const updatedRepoList = repoList.filter((repo) => repo.repositoryName !== slug); diff --git a/pages/api/v1/repositories/index.ts b/pages/api/v1/repositories/index.ts index b87e3e3..ece275c 100644 --- a/pages/api/v1/repositories/index.ts +++ b/pages/api/v1/repositories/index.ts @@ -94,14 +94,13 @@ export default async function handler( appendOnlyMode: appendOnlyMode ?? false, }; - const { stdout, stderr } = await ShellService.createRepo( + const { stdout } = await ShellService.createRepo( newRepo.sshPublicKey, newRepo.storageSize, newRepo.appendOnlyMode ?? false ); - if (stderr || !stdout) { - console.log('Create repository error: ', stderr); - throw new Error(stderr || 'Unknown error occurred while creating the repository'); + if (!stdout) { + return ApiResponse.serverError(res, 'Error creating repository'); } newRepo.repositoryName = stdout.trim();