Skip to content

Commit

Permalink
fix: show error message when user meet 403 error back from server (#123)
Browse files Browse the repository at this point in the history
fix: show error message when user meet 403 error back from server

- [x] show error message when the user meets 403 error back from the
server
- [x] show error when user selects indices drop down if the user has no
permissions
- [x] show error in the manage panel when the user's action lacks
permission

Refs: #119

---------

Signed-off-by: seven <[email protected]>
  • Loading branch information
Blankll authored Oct 19, 2024
1 parent 1d240d5 commit 21bf161
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 28 deletions.
2 changes: 0 additions & 2 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ declare module 'vue' {
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
NDropdown: typeof import('naive-ui')['NDropdown']
NDropdownItem: typeof import('naive-ui')['NDropdownItem']
NDropdownMenu: typeof import('naive-ui')['NDropdownMenu']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NFormItemRow: typeof import('naive-ui')['NFormItemRow']
Expand Down
4 changes: 4 additions & 0 deletions src/datasources/fetchApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { buildAuthHeader, buildURL, CustomError, debug } from '../common';
import { lang } from '../lang';
import { invoke } from '@tauri-apps/api/tauri';
import { get } from 'lodash';

type FetchApiOptions = {
method: string;
Expand All @@ -18,6 +19,9 @@ const handleFetch = (result: { data: unknown; status: number; details: string |
if (result.status === 401) {
throw new CustomError(result.status, lang.global.t('connection.unAuthorized'));
}
if (result.status === 403) {
throw new CustomError(result.status, get(result, 'data.error.reason', result.details || ''));
}
throw new CustomError(result.status, result.details || '');
};

Expand Down
1 change: 1 addition & 0 deletions src/lang/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export const enUS = {
port: 'Port',
username: 'Username',
password: 'Password',
indexName: 'Index/Alias',
queryParameters: 'query parameters',
sslCertVerification: 'SSL Certificate Verification',
add: 'Add connection',
Expand Down
1 change: 1 addition & 0 deletions src/lang/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export const zhCN = {
port: '端口号',
username: '用户名',
password: '密码',
indexName: '索引/别名',
queryParameters: '查询参数',
sslCertVerification: 'SSL 证书验证',
add: '添加连接',
Expand Down
31 changes: 18 additions & 13 deletions src/store/connectionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type Connection = {
username?: string;
sslCertVerification: boolean;
password?: string;
indexName?: string;
queryParameters?: string;
};
export type ConnectionIndex = {
Expand Down Expand Up @@ -76,7 +77,7 @@ export const useConnectionStore = defineStore('connectionStore', {
async testConnection(con: Connection) {
const client = loadHttpClient(con);

return await client.get(undefined, 'format=json');
return await client.get(con.indexName ?? undefined, 'format=json');
},
async saveConnection(connection: Connection) {
const index = this.connections.findIndex(({ id }: Connection) => id === connection.id);
Expand All @@ -94,18 +95,22 @@ export const useConnectionStore = defineStore('connectionStore', {
async establishConnection(connection: Connection) {
await this.testConnection(connection);
const client = loadHttpClient(connection);
const data = (await client.get('/_cat/indices', 'format=json')) as Array<{
[key: string]: string;
}>;
const indices = data.map((index: { [key: string]: string }) => ({
...index,
docs: {
count: parseInt(index['docs.count'], 10),
deleted: parseInt(index['docs.deleted'], 10),
},
store: { size: index['store.size'] },
})) as ConnectionIndex[];
this.established = { ...connection, indices };
try {
const data = (await client.get('/_cat/indices', 'format=json')) as Array<{
[key: string]: string;
}>;
const indices = data.map((index: { [key: string]: string }) => ({
...index,
docs: {
count: parseInt(index['docs.count'], 10),
deleted: parseInt(index['docs.deleted'], 10),
},
store: { size: index['store.size'] },
})) as ConnectionIndex[];
this.established = { ...connection, indices };
} catch (err) {
this.established = { ...connection, indices: [] };
}
},
async fetchIndices() {
if (!this.established) throw new Error('no connection established');
Expand Down
19 changes: 18 additions & 1 deletion src/views/connect/components/collection-selector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import { storeToRefs } from 'pinia';
import { useConnectionStore } from '../../../store';
import { useLang } from '../../../lang';
import { CustomError } from '../../../common';
const message = useMessage();
const lang = useLang();
Expand Down Expand Up @@ -44,7 +46,19 @@ const handleOpen = async (isOpen: boolean) => {
return;
}
loadingRef.value = true;
await fetchIndices();
try {
await fetchIndices();
} catch (err) {
message.error(
`status: ${(err as CustomError).status}, details: ${(err as CustomError).details}`,
{
closable: true,
keepAliveOnHover: true,
duration: 3000,
},
);
}
loadingRef.value = false;
};
</script>
Expand All @@ -56,16 +70,19 @@ const handleOpen = async (isOpen: boolean) => {
display: flex;
align-items: center;
border-right: 1px solid var(--border-color);
:deep(.n-select) {
.n-base-selection {
.n-base-selection-label {
background-color: unset;
}
.n-base-selection__border,
.n-base-selection__state-border {
border: unset;
}
}
.n-base-selection:hover,
.n-base-selection--active,
.n-base-selection--focus {
Expand Down
10 changes: 10 additions & 0 deletions src/views/connect/components/connect-dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@
/>
</n-form-item>
</n-grid-item>
<n-grid-item span="8">
<n-form-item :label="$t('connection.indexName')" path="indexName">
<n-input
v-model:value="formData.indexName"
clearable
:placeholder="$t('connection.indexName')"
/>
</n-form-item>
</n-grid-item>
<n-grid-item span="8">
<n-form-item :label="$t('connection.queryParameters')" path="queryParameters">
<n-input
Expand Down Expand Up @@ -160,6 +169,7 @@ const defaultFormData = {
port: 9200,
username: '',
password: '',
indexName: undefined,
queryParameters: '',
sslCertVerification: true,
};
Expand Down
23 changes: 17 additions & 6 deletions src/views/manage/components/index-manage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</n-tab-pane>
<template #suffix>
<div class="tab-action-group">
<n-button type="default" tertiary @click="refresh">
<n-button type="default" tertiary @click="handleRefresh">
<template #icon>
<n-icon>
<Renew />
Expand Down Expand Up @@ -275,11 +275,22 @@ const templateTable = computed(() => {
});
const refresh = async () => {
await Promise.all([fetchIndices(), fetchAliases(), fetchTemplates()]).catch(err =>
message.error(err.message, { closable: true, keepAliveOnHover: true }),
);
await Promise.all([fetchIndices(), fetchAliases(), fetchTemplates()]);
};
const handleRefresh = async () => {
try {
await refresh();
} catch (err) {
message.error(
`status: ${(err as CustomError).status}, details: ${(err as CustomError).details}`,
{
closable: true,
keepAliveOnHover: true,
duration: 3000,
},
);
}
};
const toggleModal = (target: string) => {
if (target === 'index') indexDialogRef.value.toggleModal();
if (target === 'alias') aliasDialogRef.value.toggleModal();
Expand Down Expand Up @@ -362,7 +373,7 @@ const handleAction = async (action: string, indexName: string, aliasName?: strin
};
onMounted(async () => {
await refresh();
await handleRefresh();
});
</script>

Expand Down
13 changes: 12 additions & 1 deletion src/views/manage/components/node-state.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ const clusterManageStore = useClusterManageStore();
const { fetchNodes, fetchNodeState } = clusterManageStore;
const { nodes } = storeToRefs(clusterManageStore);
const message = useMessage();
type NodeStats = {
key: string;
value: string | number;
Expand Down Expand Up @@ -120,7 +122,16 @@ const handleNodeClick = async (nodeName: string) => {
{ name: 'heap', ...heap },
];
};
fetchNodes();
onMounted(() => {
fetchNodes().catch(err => {
message.error(`status: ${err.status}, details: ${err.details}`, {
closable: true,
keepAliveOnHover: true,
duration: 3000,
});
});
});
</script>

<style scoped lang="scss">
Expand Down
16 changes: 15 additions & 1 deletion src/views/manage/components/shared-manage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ import {
import { Memory } from '@vicons/fa';
import { NButton } from 'naive-ui';
import { TableColumn } from 'naive-ui/es/data-table/src/interface';
import { CustomError } from '../../../common';
const clusterManageStore = useClusterManageStore();
const { fetchNodes, fetchShards, getShardState } = clusterManageStore;
const { shards, nodesWithShards } = storeToRefs(clusterManageStore);
const message = useMessage();
type IndexShard = ShardState & {
details: Array<{
Expand Down Expand Up @@ -136,8 +138,20 @@ const indexShards = ref<{
index: string;
shards: Array<IndexShard>;
}>();
const refreshShards = async () => {
await Promise.all([fetchNodes(), fetchShards()]);
try {
await Promise.all([fetchNodes(), fetchShards()]);
} catch (err) {
message.error(
`status: ${(err as CustomError).status}, details: ${(err as CustomError).details}`,
{
closable: true,
keepAliveOnHover: true,
duration: 3000,
},
);
}
};
const handleShardClick = async (shard: Shard) => {
Expand Down
44 changes: 40 additions & 4 deletions src/views/manage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,62 @@ import { useClusterManageStore, useConnectionStore } from '../../store';
import { storeToRefs } from 'pinia';
import NodeState from './components/node-state.vue';
import SharedManage from './components/shared-manage.vue';
import { lang } from '../../lang';
import { useLang } from '../../lang';
import IndexManage from './components/index-manage.vue';
import { CustomError } from '../../common';
const activeTab = ref(lang.global.t('manage.cluster'));
const lang = useLang();
const activeTab = ref(lang.t('manage.cluster'));
const connectionStore = useConnectionStore();
const { established } = storeToRefs(connectionStore);
const message = useMessage();
const clusterManageStore = useClusterManageStore();
const { fetchCluster, fetchIndices, fetchAliases, fetchNodes, fetchShards } = clusterManageStore;
const { cluster } = storeToRefs(clusterManageStore);
watch(established, async () => {
await Promise.all([fetchCluster(), fetchIndices(), fetchAliases(), fetchNodes(), fetchShards()]);
try {
await Promise.all([
fetchCluster(),
fetchIndices(),
fetchAliases(),
fetchNodes(),
fetchShards(),
]);
} catch (err) {
message.error(
`status: ${(err as CustomError).status}, details: ${(err as CustomError).details}`,
{
closable: true,
keepAliveOnHover: true,
duration: 3000,
},
);
cluster.value = null;
}
});
const handleManageTabChange = (tab: string) => {
activeTab.value = tab;
};
fetchCluster().catch(() => {});
fetchCluster().catch(err =>
!established.value?.id
? message.warning(lang.t('editor.establishedRequired'), {
closable: true,
keepAliveOnHover: true,
duration: 3000,
})
: message.error(`status: ${err.status}, details: ${err.details}`, {
closable: true,
keepAliveOnHover: true,
duration: 3000,
}),
);
</script>

<style lang="scss" scoped>
Expand Down

0 comments on commit 21bf161

Please sign in to comment.