diff --git a/components.d.ts b/components.d.ts index 5400788d..0836dfa2 100644 --- a/components.d.ts +++ b/components.d.ts @@ -21,6 +21,7 @@ declare module 'vue' { NGridItem: typeof import('naive-ui')['NGridItem'] NIcon: typeof import('naive-ui')['NIcon'] NInput: typeof import('naive-ui')['NInput'] + NInputNumber: typeof import('naive-ui')['NInputNumber'] NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider'] NMessageProvider: typeof import('naive-ui')['NMessageProvider'] NModal: typeof import('naive-ui')['NModal'] diff --git a/src/common/httpClient.ts b/src/common/httpClient.ts index a30f05b3..63c8831c 100644 --- a/src/common/httpClient.ts +++ b/src/common/httpClient.ts @@ -1,8 +1,12 @@ import { CustomError } from './customError'; import { Buffer } from 'buffer'; +import { lang } from '../lang'; const catchHandler = (err: unknown) => { if (err instanceof CustomError) { + if (err.status === 401) { + throw new CustomError(err.status, lang.global.t('connection.unAuthorized')); + } throw new CustomError(err.status, err.details); } if (err instanceof Error) { @@ -18,81 +22,81 @@ const buildURL = (host: string, port: number, path?: string, queryParameters?: s return url; }; - -export const loadHttpClient = ({ +const fetchWrapper = async ({ + method, + path, + queryParameters, + payload, host, port, username, password, }: { + method: string; + path?: string; + queryParameters?: string; + payload?: unknown; + username?: string; + password?: string; + host: string; + port: number; +}) => { + const authorization = + username && password + ? `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` + : undefined; + + const url = buildURL(host, port, path, queryParameters); + try { + const result = await fetch(url, { + method, + headers: { 'Content-Type': 'application/json', authorization } as unknown as Headers, + body: payload ? JSON.stringify(payload) : undefined, + }); + if (result.ok) { + return await result.json(); + } + throw new CustomError(result.status, await result.text()); + } catch (e) { + throw catchHandler(e); + } +}; +export const loadHttpClient = (con: { host: string; port: number; username?: string; password?: string; }) => ({ - get: async (path?: string, queryParameters?: string) => { - const authorization = - username && password - ? `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` - : undefined; - const url = buildURL(host, port, path, queryParameters); - try { - const result = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json', authorization } as unknown as Headers, - }); - const data = await result.json(); - if (!result.ok) new CustomError(result.status, data); + get: async (path?: string, queryParameters?: string) => + fetchWrapper({ + ...con, + method: 'GET', + path, + queryParameters, + }), + post: async (path: string, queryParameters?: string, payload?: unknown) => + fetchWrapper({ + ...con, + method: 'POST', + path, + queryParameters, + payload, + }), + put: async (path: string, queryParameters?: string, payload?: unknown) => + fetchWrapper({ + ...con, + method: 'PUT', + path, + queryParameters, + payload, + }), - return data; - } catch (e) { - throw catchHandler(e); - } - }, - post: async (path: string, queryParameters?: string, payload?: unknown) => { - const url = buildURL(host, port, path, queryParameters); - try { - const result = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: payload ? JSON.stringify(payload) : undefined, - }); - const data = await result.json(); - if (!result.ok) new CustomError(result.status, data); - return data; - } catch (e) { - throw catchHandler(e); - } - }, - put: async (path: string, queryParameters?: string, payload?: unknown) => { - const url = buildURL(host, port, path, queryParameters); - try { - const result = await fetch(url, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: payload ? JSON.stringify(payload) : undefined, - }); - const data = await result.json(); - if (!result.ok) new CustomError(result.status, data); - return data; - } catch (e) { - throw catchHandler(e); - } - }, - - delete: async (path: string, queryParameters?: string, payload?: unknown) => { - const url = buildURL(host, port, path, queryParameters); - try { - const result = await fetch(url, { - method: 'delete', - headers: { 'Content-Type': 'application/json' }, - body: payload ? JSON.stringify(payload) : undefined, - }); - const data = await result.json(); - if (!result.ok) new CustomError(result.status, data); - return data; - } catch (e) { - throw catchHandler(e); - } - }, + delete: async (path: string, queryParameters?: string, payload?: unknown) => + fetchWrapper({ + ...con, + method: 'DELETE', + path, + queryParameters, + payload, + }), }); diff --git a/src/lang/index.ts b/src/lang/index.ts index 6ba851c7..1df278c3 100644 --- a/src/lang/index.ts +++ b/src/lang/index.ts @@ -35,6 +35,7 @@ const enUS = { edit: 'Edit', remove: 'Remove', }, + unAuthorized: 'Authorization failed, ensure your username and password are correct', }, dialogOps: { warning: 'Warning', @@ -84,6 +85,7 @@ const zhCN = { edit: '编辑', remove: '删除', }, + unAuthorized: '认证失败,请输入正确的用户名和密码!', }, dialogOps: { warning: '提示', diff --git a/src/store/connectionStore.ts b/src/store/connectionStore.ts index a28e96d2..7f454e6b 100644 --- a/src/store/connectionStore.ts +++ b/src/store/connectionStore.ts @@ -6,7 +6,7 @@ export type Connection = { id?: number; name: string; host: string; - port: number | string; + port: number; username?: string; password?: string; queryParameters?: string; @@ -60,13 +60,10 @@ export const useConnectionStore = defineStore('connectionStore', { async fetchConnections() { this.connections = await storeAPI.get('connections', []); }, - async testConnection({ port, ...con }: Connection) { - const client = loadHttpClient({ - ...con, - port: parseInt(`${port}`, 10), - }); + async testConnection(con: Connection) { + const client = loadHttpClient(con); - return await client.get(); + return await client.get(undefined, 'format=json'); }, saveConnection(connection: Connection) { const index = this.connections.findIndex(item => item.id === connection.id); @@ -83,10 +80,7 @@ export const useConnectionStore = defineStore('connectionStore', { }, async establishConnection(connection: Connection) { await this.testConnection(connection); - const client = loadHttpClient({ - ...connection, - port: parseInt(`${connection.port}`, 10), - }); + const client = loadHttpClient(connection); const data = await client.get('/_cat/indices', 'format=json'); const indices = data.map((index: { [key: string]: string }) => ({ @@ -117,10 +111,7 @@ export const useConnectionStore = defineStore('connectionStore', { qdsl?: string; }) { if (!this.established) throw new Error('no connection established'); - const client = loadHttpClient({ - ...this.established, - port: parseInt(`${this.established.port}`, 10), - }); + const client = loadHttpClient(this.established); const reqPath = buildPath(index, path); const body = qdsl ? JSON.parse(qdsl) : undefined; diff --git a/src/views/connect/components/connect-dialog.vue b/src/views/connect/components/connect-dialog.vue index 8ce1d79b..7565d0de 100644 --- a/src/views/connect/components/connect-dialog.vue +++ b/src/views/connect/components/connect-dialog.vue @@ -7,6 +7,7 @@ :title="modalTitle" :bordered="false" class="add-connect-modal-card" + @mask-click="closeModal" >