feat(frontend): create orchestrated waf rules

This commit is contained in:
ryan
2026-07-13 12:00:24 +08:00
parent af20e2e838
commit 4000366856
13 changed files with 539 additions and 493 deletions
+3
View File
@@ -211,6 +211,9 @@ export type {
ApplyLogList,
DashboardOverview,
WAFIPGroup,
WAFRule,
WAFRuleGraph,
WAFRuleNode,
WAFRuleGroup,
WAFSiteRuleGroups,
TlsCertificateItem,
+6
View File
@@ -70,6 +70,12 @@ export type {
WAFIPGroupSyncResult,
WAFIPGroupSubscriptionFormat,
WAFIPGroupType,
WAFCreateRulePayload,
WAFRule,
WAFRuleEdge,
WAFRuleGraph,
WAFRuleNode,
WAFSaveRuleGraphPayload,
WAFRuleGroup,
WAFRuleGroupPayload,
WAFSiteRuleGroups,
+69 -8
View File
@@ -1,3 +1,5 @@
import type {XYPosition} from '@xyflow/react';
export type ReleaseChannel = 'stable' | 'preview';
export type NodeType = 'edge_node' | 'tunnel_relay' | 'tunnel_client';
@@ -689,11 +691,65 @@ export interface OpenFlarePublicStatus {
system_name: string;
}
export interface WAFRuleGroup {
export interface IPMatchConfig {
ips: string[];
cidrs: string[];
ip_group_ids: number[];
}
export interface GeoMatchConfig {
countries: string[];
regions: string[];
}
export interface PoWNodeConfig {
algorithm: 'fast' | 'slow';
difficulty: number;
session_ttl: number;
challenge_ttl: number;
}
export interface BlockNodeConfig {
status_code: number;
response_body: string;
}
export type WAFRuleNode =
| {id: string; type: 'start'; position: XYPosition; config: Record<string, never>}
| {id: string; type: 'ip_match'; position: XYPosition; config: IPMatchConfig}
| {id: string; type: 'geo_match'; position: XYPosition; config: GeoMatchConfig}
| {id: string; type: 'pow'; position: XYPosition; config: PoWNodeConfig}
| {id: string; type: 'allow'; position: XYPosition; config: Record<string, never>}
| {id: string; type: 'block'; position: XYPosition; config: BlockNodeConfig};
export interface WAFRuleEdge {
id: string;
source: string;
source_handle: string;
target: string;
}
export interface WAFRuleGraph {
schema_version: number;
nodes: WAFRuleNode[];
edges: WAFRuleEdge[];
}
export interface WAFRule {
id: number;
name: string;
enabled: boolean;
is_global: boolean;
graph: WAFRuleGraph;
revision: number;
applied_site_ids: number[];
applied_site_count: number;
created_at: string;
updated_at: string;
}
/** @deprecated Legacy fixed-chain rule shape retained for untouched binding consumers. */
export interface WAFRuleGroup extends WAFRule {
block_status_code: number;
block_response_body: string;
ip_whitelist: string[];
@@ -706,10 +762,15 @@ export interface WAFRuleGroup {
region_blacklist: string[];
pow_enabled: boolean;
pow_config: ProxyRoutePoWConfig;
applied_site_ids: number[];
applied_site_count: number;
created_at: string;
updated_at: string;
}
export interface WAFCreateRulePayload {
name: string;
}
export interface WAFSaveRuleGraphPayload {
revision: number;
graph: WAFRuleGraph;
}
export interface WAFRuleGroupPayload {
@@ -731,9 +792,9 @@ export interface WAFRuleGroupPayload {
export interface WAFSiteRuleGroups {
route_id: number;
global_rule_group: WAFRuleGroup | null;
rule_groups: WAFRuleGroup[];
applied_rule_groups: WAFRuleGroup[];
global_rule_group: WAFRule | null;
rule_groups: WAFRule[];
applied_rule_groups: WAFRule[];
applied_ids: number[];
}
+16 -15
View File
@@ -5,39 +5,40 @@ import type {
WAFIPGroupAutoTestResult,
WAFIPGroupPayload,
WAFIPGroupSyncResult,
WAFRuleGroup,
WAFRuleGroupPayload,
WAFCreateRulePayload,
WAFRule,
WAFSaveRuleGraphPayload,
WAFSiteRuleGroups,
} from './types';
export class WafService extends OpenFlareBaseService {
protected static override readonly basePath: string = '/api/v1/d/waf';
static async listRuleGroups(): Promise<WAFRuleGroup[]> {
return this.get<WAFRuleGroup[]>('/rule-groups');
static async listRuleGroups(): Promise<WAFRule[]> {
return this.get<WAFRule[]>('/rule-groups');
}
static async getRuleGroup(id: number): Promise<WAFRuleGroup> {
return this.get<WAFRuleGroup>(`/rule-groups/${id}`);
static async getRule(id: number): Promise<WAFRule> {
return this.get<WAFRule>(`/rule-groups/${id}`);
}
static async createRuleGroup(payload: WAFRuleGroupPayload): Promise<WAFRuleGroup> {
return this.post<WAFRuleGroup>('/rule-groups', payload);
static async createRule(payload: WAFCreateRulePayload): Promise<WAFRule> {
return this.post<WAFRule>('/rule-groups', payload);
}
static async updateRuleGroup(
static async saveRuleGraph(
id: number,
payload: WAFRuleGroupPayload,
): Promise<WAFRuleGroup> {
return this.post<WAFRuleGroup>(`/rule-groups/${id}/update`, payload);
payload: WAFSaveRuleGraphPayload,
): Promise<WAFRule> {
return this.post<WAFRule>(`/rule-groups/${id}/graph`, payload);
}
static async deleteRuleGroup(id: number): Promise<void> {
return this.post<void>(`/rule-groups/${id}/delete`);
}
static async updateRuleGroupSites(id: number, ids: number[]): Promise<WAFRuleGroup> {
return this.post<WAFRuleGroup>(`/rule-groups/${id}/sites`, { ids });
static async updateRuleGroupSites(id: number, ids: number[]): Promise<WAFRule> {
return this.post<WAFRule>(`/rule-groups/${id}/sites`, { ids });
}
static async listSiteRuleGroups(routeId: number): Promise<WAFSiteRuleGroups> {
@@ -82,4 +83,4 @@ export class WafService extends OpenFlareBaseService {
static async syncIPGroup(id: number): Promise<WAFIPGroupSyncResult> {
return this.post<WAFIPGroupSyncResult>(`/ip-groups/${id}/sync`);
}
}
}