diff --git a/pages/api/account/getWizardEnv.ts b/pages/api/account/getWizardEnv.ts index 8c74884..8e22505 100644 --- a/pages/api/account/getWizardEnv.ts +++ b/pages/api/account/getWizardEnv.ts @@ -1,48 +1,45 @@ //Lib import { authOptions } from '~/pages/api/auth/[...nextauth]'; import { getServerSession } from 'next-auth/next'; -import { WizardEnvEnum } from '~/types/domain/config.types'; +import { WizardEnvEnum, WizardEnvType } from '~/types/domain/config.types'; import { NextApiRequest, NextApiResponse } from 'next'; +import { ErrorResponse } from '~/types/api/error.types'; -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method == 'GET') { - //AUTHENTICATION - const session = await getServerSession(req, res, authOptions); - if (!session) { - res.status(401).json({ message: 'You must be logged in.' }); - return; +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== 'GET') { + return res.status(405); + } + const session = await getServerSession(req, res, authOptions); + if (!session) { + return res.status(401); + } + + try { + function getEnvVariable(envName: WizardEnvEnum, defaultValue = '') { + return process.env[envName] || defaultValue; } - try { - function getEnvVariable(envName: WizardEnvEnum, defaultValue = '') { - return process.env[envName] || defaultValue; - } + const wizardEnv: WizardEnvType = { + UNIX_USER: getEnvVariable(WizardEnvEnum.UNIX_USER, 'borgwarehouse'), + FQDN: getEnvVariable(WizardEnvEnum.FQDN, 'localhost'), + SSH_SERVER_PORT: getEnvVariable(WizardEnvEnum.SSH_SERVER_PORT, '22'), + FQDN_LAN: getEnvVariable(WizardEnvEnum.FQDN_LAN), + SSH_SERVER_PORT_LAN: getEnvVariable(WizardEnvEnum.SSH_SERVER_PORT_LAN), + SSH_SERVER_FINGERPRINT_RSA: getEnvVariable(WizardEnvEnum.SSH_SERVER_FINGERPRINT_RSA), + SSH_SERVER_FINGERPRINT_ED25519: getEnvVariable(WizardEnvEnum.SSH_SERVER_FINGERPRINT_ED25519), + SSH_SERVER_FINGERPRINT_ECDSA: getEnvVariable(WizardEnvEnum.SSH_SERVER_FINGERPRINT_ECDSA), + HIDE_SSH_PORT: getEnvVariable(WizardEnvEnum.HIDE_SSH_PORT, 'false'), + DISABLE_INTEGRATIONS: getEnvVariable(WizardEnvEnum.DISABLE_INTEGRATIONS, 'false'), + DISABLE_DELETE_REPO: getEnvVariable(WizardEnvEnum.DISABLE_DELETE_REPO, 'false'), + }; - const wizardEnv = { - UNIX_USER: getEnvVariable(WizardEnvEnum.UNIX_USER, 'borgwarehouse'), - FQDN: getEnvVariable(WizardEnvEnum.FQDN, 'localhost'), - SSH_SERVER_PORT: getEnvVariable(WizardEnvEnum.SSH_SERVER_PORT, '22'), - FQDN_LAN: getEnvVariable(WizardEnvEnum.FQDN_LAN), - SSH_SERVER_PORT_LAN: getEnvVariable(WizardEnvEnum.SSH_SERVER_PORT_LAN), - SSH_SERVER_FINGERPRINT_RSA: getEnvVariable(WizardEnvEnum.SSH_SERVER_FINGERPRINT_RSA), - SSH_SERVER_FINGERPRINT_ED25519: getEnvVariable( - WizardEnvEnum.SSH_SERVER_FINGERPRINT_ED25519 - ), - SSH_SERVER_FINGERPRINT_ECDSA: getEnvVariable(WizardEnvEnum.SSH_SERVER_FINGERPRINT_ECDSA), - HIDE_SSH_PORT: getEnvVariable(WizardEnvEnum.HIDE_SSH_PORT, 'false'), - DISABLE_INTEGRATIONS: getEnvVariable(WizardEnvEnum.DISABLE_INTEGRATIONS, 'false'), - }; - - res.status(200).json({ wizardEnv }); - return; - } catch (error) { - console.log(error); - res.status(500).json({ - message: 'API error, contact the administrator', - }); - return; - } - } else { - res.status(405).json({ message: 'Bad request on API' }); + res.status(200).json(wizardEnv); + return; + } catch (error) { + console.log(error); + return res.status(500); } } diff --git a/tests/supertest/getAppriseAlert.test.ts b/tests/supertest/getAppriseAlert.test.ts new file mode 100644 index 0000000..720f5b3 --- /dev/null +++ b/tests/supertest/getAppriseAlert.test.ts @@ -0,0 +1,76 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/getAppriseAlert'; +import { getServerSession } from 'next-auth/next'; +import { promises as fs } from 'fs'; +import path from 'path'; + +jest.mock('next-auth/next'); +jest.mock('fs', () => ({ + promises: { + readFile: jest.fn(), + }, +})); + +describe('Get Apprise Alert API', () => { + it('should return 405 if the method is not GET', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 401 if the user is not authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue(null); + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(401); + expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' }); + }); + + it('should return 400 if the user does not exist', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'nonexistent' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', appriseAlert: true }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return appriseAlert value if the user exists', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', appriseAlert: true }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ appriseAlert: true }); + }); + + it('should return 500 if there is an error reading the file', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory' }); + }); +}); diff --git a/tests/supertest/getAppriseMode.test.ts b/tests/supertest/getAppriseMode.test.ts new file mode 100644 index 0000000..368490e --- /dev/null +++ b/tests/supertest/getAppriseMode.test.ts @@ -0,0 +1,91 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/getAppriseMode'; +import { getServerSession } from 'next-auth/next'; +import { promises as fs } from 'fs'; +import path from 'path'; + +jest.mock('next-auth/next'); +jest.mock('fs', () => ({ + promises: { + readFile: jest.fn(), + }, +})); + +describe('Get Apprise Mode API', () => { + it('should return 405 if the method is not GET', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 401 if the user is not authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue(null); + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(401); + expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' }); + }); + + it('should return 400 if the user does not exist', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'nonexistent' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([ + { + username: 'testuser', + appriseMode: 'stateless', + appriseStatelessURL: 'https://example.com', + }, + ]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return appriseMode and appriseStatelessURL if the user exists', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([ + { + username: 'testuser', + appriseMode: 'stateless', + appriseStatelessURL: 'https://example.com', + }, + ]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ + appriseMode: 'stateless', + appriseStatelessURL: 'https://example.com', + }); + }); + + it('should return 500 if there is an error reading the file', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory' }); + }); +}); diff --git a/tests/supertest/getAppriseServices.test.ts b/tests/supertest/getAppriseServices.test.ts new file mode 100644 index 0000000..b277e04 --- /dev/null +++ b/tests/supertest/getAppriseServices.test.ts @@ -0,0 +1,78 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/getAppriseServices'; +import { getServerSession } from 'next-auth/next'; +import { promises as fs } from 'fs'; +import path from 'path'; + +jest.mock('next-auth/next'); +jest.mock('fs', () => ({ + promises: { + readFile: jest.fn(), + }, +})); + +describe('Get Apprise Services API', () => { + it('should return 405 if the method is not GET', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 401 if the user is not authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue(null); + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(401); + expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' }); + }); + + it('should return 400 if the user does not exist', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'nonexistent' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', appriseServices: ['service1', 'service2'] }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return appriseServices if the user exists', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', appriseServices: ['service1', 'service2'] }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ + appriseServices: ['service1', 'service2'], + }); + }); + + it('should return 500 if there is an error reading the file', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory' }); + }); +}); diff --git a/tests/supertest/getEmailAlert.test.ts b/tests/supertest/getEmailAlert.test.ts new file mode 100644 index 0000000..168a1da --- /dev/null +++ b/tests/supertest/getEmailAlert.test.ts @@ -0,0 +1,78 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/getEmailAlert'; +import { getServerSession } from 'next-auth/next'; +import { promises as fs } from 'fs'; +import path from 'path'; + +jest.mock('next-auth/next'); +jest.mock('fs', () => ({ + promises: { + readFile: jest.fn(), + }, +})); + +describe('Get Email Alert API', () => { + it('should return 405 if the method is not GET', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 401 if the user is not authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue(null); + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(401); + expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' }); + }); + + it('should return 400 if the user does not exist', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'nonexistent' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', emailAlert: true }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return emailAlert if the user exists', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockResolvedValue( + JSON.stringify([{ username: 'testuser', emailAlert: true }]) + ); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ + emailAlert: true, + }); + }); + + it('should return 500 if there is an error reading the file', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ + user: { name: 'testuser' }, + }); + + (fs.readFile as jest.Mock).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory' }); + }); +}); diff --git a/tests/supertest/getWizardEnv.test.ts b/tests/supertest/getWizardEnv.test.ts new file mode 100644 index 0000000..013cc3c --- /dev/null +++ b/tests/supertest/getWizardEnv.test.ts @@ -0,0 +1,51 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/getWizardEnv'; +import { getServerSession } from 'next-auth/next'; +import { WizardEnvEnum } from '~/types/domain/config.types'; + +jest.mock('next-auth/next'); + +describe('Get Wizard Env API', () => { + it('should return 405 if the method is not GET', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 401 if the user is not authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue(null); + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + expect(res._getStatusCode()).toBe(401); + }); + + it('should return 200 with wizardEnv if the user is authenticated', async () => { + (getServerSession as jest.Mock).mockResolvedValue({ user: { name: 'testuser' } }); + + process.env.UNIX_USER = 'borgwarehouse'; + process.env.FQDN = 'localhost'; + process.env.SSH_SERVER_PORT = '22'; + process.env.HIDE_SSH_PORT = 'false'; + process.env.DISABLE_INTEGRATIONS = 'false'; + + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ + wizardEnv: { + UNIX_USER: 'borgwarehouse', + FQDN: 'localhost', + SSH_SERVER_PORT: '22', + FQDN_LAN: '', + SSH_SERVER_PORT_LAN: '', + SSH_SERVER_FINGERPRINT_RSA: '', + SSH_SERVER_FINGERPRINT_ED25519: '', + SSH_SERVER_FINGERPRINT_ECDSA: '', + HIDE_SSH_PORT: 'false', + DISABLE_INTEGRATIONS: 'false', + DISABLE_DELETE_REPO: 'false', + }, + }); + }); +}); diff --git a/types/api/settings.types.ts b/types/api/settings.types.ts index febfda8..9b1abfc 100644 --- a/types/api/settings.types.ts +++ b/types/api/settings.types.ts @@ -2,7 +2,7 @@ export type EmailSettingDTO = { email: string; }; -export type UserSettingDTO = { +export type UsernameSettingDTO = { username: string; };