+
diff --git a/src/app/pages/index.vue b/src/app/pages/index.vue
index 4168eb28..a4f27efe 100644
--- a/src/app/pages/index.vue
+++ b/src/app/pages/index.vue
@@ -4,6 +4,7 @@
+
diff --git a/src/app/stores/clients.ts b/src/app/stores/clients.ts
index d1c621ec..ed2f9498 100644
--- a/src/app/stores/clients.ts
+++ b/src/app/stores/clients.ts
@@ -31,8 +31,13 @@ export const useClientsStore = defineStore('Clients', () => {
const clients = ref(null);
const clientsPersist = ref>({});
+ const searchParams = ref({
+ filter: '',
+ });
+
const { data: _clients, refresh: _refresh } = useFetch('/api/client', {
method: 'get',
+ params: searchParams,
});
// TODO: rewrite
@@ -130,5 +135,11 @@ export const useClientsStore = defineStore('Clients', () => {
clients.value = transformedClients ?? null;
}
- return { clients, clientsPersist, refresh, _clients };
+
+ function setSearchQuery(filter: string) {
+ clients.value = null;
+ searchParams.value.filter = filter;
+ }
+
+ return { clients, clientsPersist, refresh, _clients, setSearchQuery };
});
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 73dba722..f76022cc 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -116,7 +116,8 @@
"dnsDesc": "DNS server clients will use (overrides global config)",
"notConnected": "Client not connected",
"endpoint": "Endpoint",
- "endpointDesc": "IP of the client from which the WireGuard connection is established"
+ "endpointDesc": "IP of the client from which the WireGuard connection is established",
+ "search": "Search clients..."
},
"dialog": {
"change": "Change",
diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json
index 7c95a43b..938f5a16 100644
--- a/src/i18n/locales/zh-CN.json
+++ b/src/i18n/locales/zh-CN.json
@@ -112,7 +112,8 @@
"persistentKeepaliveDesc": "设置保活数据包的发送间隔(秒)。0表示禁用",
"hooks": "钩子脚本",
"hooksDescription": "钩子脚本仅在使用wg-quick时有效",
- "hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段"
+ "hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段",
+ "search": "搜索客户端..."
},
"dialog": {
"change": "确认修改",
diff --git a/src/i18n/locales/zh-HK.json b/src/i18n/locales/zh-HK.json
index b2d80cac..41e7001b 100644
--- a/src/i18n/locales/zh-HK.json
+++ b/src/i18n/locales/zh-HK.json
@@ -113,7 +113,8 @@
"hooks": "掛鉤",
"hooksDescription": "掛鉤僅適用於wg-quick",
"hooksLeaveEmpty": "僅適用於wg-quick,否則請留空",
- "dnsDesc": "客戶端使用的域名系統伺服器(取代全局配置)"
+ "dnsDesc": "客戶端使用的域名系統伺服器(取代全局配置)",
+ "search": "搜尋客戶端..."
},
"dialog": {
"change": "更改",
diff --git a/src/server/api/client/index.get.ts b/src/server/api/client/index.get.ts
index 296e0003..812cd190 100644
--- a/src/server/api/client/index.get.ts
+++ b/src/server/api/client/index.get.ts
@@ -1,6 +1,11 @@
-export default definePermissionEventHandler('clients', 'custom', ({ user }) => {
- if (user.role === roles.ADMIN) {
- return WireGuard.getAllClients();
+export default definePermissionEventHandler(
+ 'clients',
+ 'custom',
+ ({ event, user }) => {
+ const { filter } = getQuery(event);
+ if (user.role === roles.ADMIN) {
+ return WireGuard.filterClients(null, filter as string);
+ }
+ return WireGuard.filterClients(user.id, filter as string);
}
- return WireGuard.getClientsForUser(user.id);
-});
+);
diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts
index 034561c4..5044ee06 100644
--- a/src/server/utils/WireGuard.ts
+++ b/src/server/utils/WireGuard.ts
@@ -134,6 +134,29 @@ class WireGuard {
return clients;
}
+ async filterClients(userId: ID | null, filter: string) {
+ let clients;
+ if (userId != null) {
+ await this.getClientsForUser(userId);
+ } else {
+ clients = await this.getAllClients();
+ }
+
+ if (!clients) {
+ return [];
+ }
+
+ if (!filter.trim()) return clients;
+
+ const searchTerm = filter.toLowerCase().trim();
+ return clients?.filter((client) => {
+ const nameMatches = client.name.toLowerCase().includes(searchTerm);
+ const ipv4Matches = client.ipv4Address.toLowerCase().includes(searchTerm);
+ const ipv6Matches = client.ipv6Address.toLowerCase().includes(searchTerm);
+ return nameMatches || ipv4Matches || ipv6Matches;
+ });
+ }
+
async getClientConfiguration({ clientId }: { clientId: ID }) {
const wgInterface = await Database.interfaces.get();
const userConfig = await Database.userConfigs.get();