BREAKING CHANGE(vpn): replace tag-based VPN access control with source and target profiles
This commit is contained in:
@@ -116,7 +116,7 @@ export const configStatePart = await appState.getStatePart<IConfigState>(
|
||||
// Determine initial view from URL path
|
||||
const getInitialView = (): string => {
|
||||
const path = typeof window !== 'undefined' ? window.location.pathname : '/';
|
||||
const validViews = ['overview', 'network', 'emails', 'logs', 'routes', 'apitokens', 'configuration', 'security', 'certificates', 'remoteingress', 'securityprofiles', 'networktargets'];
|
||||
const validViews = ['overview', 'network', 'emails', 'logs', 'routes', 'apitokens', 'configuration', 'security', 'certificates', 'remoteingress', 'sourceprofiles', 'networktargets', 'targetprofiles'];
|
||||
const segments = path.split('/').filter(Boolean);
|
||||
const view = segments[0];
|
||||
return validViews.includes(view) ? view : 'overview';
|
||||
@@ -459,12 +459,19 @@ export const setActiveViewAction = uiStatePart.createAction<string>(async (state
|
||||
}
|
||||
|
||||
// If switching to security profiles or network targets views, fetch profiles/targets data
|
||||
if ((viewName === 'securityprofiles' || viewName === 'networktargets') && currentState.activeView !== viewName) {
|
||||
if ((viewName === 'sourceprofiles' || viewName === 'networktargets') && currentState.activeView !== viewName) {
|
||||
setTimeout(() => {
|
||||
profilesTargetsStatePart.dispatchAction(fetchProfilesAndTargetsAction, null);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// If switching to target profiles view, fetch target profiles data
|
||||
if (viewName === 'targetprofiles' && currentState.activeView !== viewName) {
|
||||
setTimeout(() => {
|
||||
targetProfilesStatePart.dispatchAction(fetchTargetProfilesAction, null);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
return {
|
||||
...currentState,
|
||||
activeView: viewName,
|
||||
@@ -1006,7 +1013,7 @@ export const fetchVpnAction = vpnStatePart.createAction(async (statePartArg): Pr
|
||||
|
||||
export const createVpnClientAction = vpnStatePart.createAction<{
|
||||
clientId: string;
|
||||
serverDefinedClientTags?: string[];
|
||||
targetProfileIds?: string[];
|
||||
description?: string;
|
||||
forceDestinationSmartproxy?: boolean;
|
||||
destinationAllowList?: string[];
|
||||
@@ -1028,7 +1035,7 @@ export const createVpnClientAction = vpnStatePart.createAction<{
|
||||
const response = await request.fire({
|
||||
identity: context.identity!,
|
||||
clientId: dataArg.clientId,
|
||||
serverDefinedClientTags: dataArg.serverDefinedClientTags,
|
||||
targetProfileIds: dataArg.targetProfileIds,
|
||||
description: dataArg.description,
|
||||
forceDestinationSmartproxy: dataArg.forceDestinationSmartproxy,
|
||||
destinationAllowList: dataArg.destinationAllowList,
|
||||
@@ -1105,7 +1112,7 @@ export const toggleVpnClientAction = vpnStatePart.createAction<{
|
||||
export const updateVpnClientAction = vpnStatePart.createAction<{
|
||||
clientId: string;
|
||||
description?: string;
|
||||
serverDefinedClientTags?: string[];
|
||||
targetProfileIds?: string[];
|
||||
forceDestinationSmartproxy?: boolean;
|
||||
destinationAllowList?: string[];
|
||||
destinationBlockList?: string[];
|
||||
@@ -1127,7 +1134,7 @@ export const updateVpnClientAction = vpnStatePart.createAction<{
|
||||
identity: context.identity!,
|
||||
clientId: dataArg.clientId,
|
||||
description: dataArg.description,
|
||||
serverDefinedClientTags: dataArg.serverDefinedClientTags,
|
||||
targetProfileIds: dataArg.targetProfileIds,
|
||||
forceDestinationSmartproxy: dataArg.forceDestinationSmartproxy,
|
||||
destinationAllowList: dataArg.destinationAllowList,
|
||||
destinationBlockList: dataArg.destinationBlockList,
|
||||
@@ -1158,11 +1165,167 @@ export const clearNewClientConfigAction = vpnStatePart.createAction(
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Security Profiles & Network Targets State
|
||||
// Target Profiles State
|
||||
// ============================================================================
|
||||
|
||||
export interface ITargetProfilesState {
|
||||
profiles: interfaces.data.ITargetProfile[];
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
lastUpdated: number;
|
||||
}
|
||||
|
||||
export const targetProfilesStatePart = await appState.getStatePart<ITargetProfilesState>(
|
||||
'targetProfiles',
|
||||
{
|
||||
profiles: [],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
lastUpdated: 0,
|
||||
},
|
||||
'soft'
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Target Profiles Actions
|
||||
// ============================================================================
|
||||
|
||||
export const fetchTargetProfilesAction = targetProfilesStatePart.createAction(
|
||||
async (statePartArg): Promise<ITargetProfilesState> => {
|
||||
const context = getActionContext();
|
||||
const currentState = statePartArg.getState()!;
|
||||
if (!context.identity) return currentState;
|
||||
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_GetTargetProfiles
|
||||
>('/typedrequest', 'getTargetProfiles');
|
||||
|
||||
const response = await request.fire({ identity: context.identity });
|
||||
|
||||
return {
|
||||
profiles: response.profiles,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
lastUpdated: Date.now(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
...currentState,
|
||||
isLoading: false,
|
||||
error: error instanceof Error ? error.message : 'Failed to fetch target profiles',
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const createTargetProfileAction = targetProfilesStatePart.createAction<{
|
||||
name: string;
|
||||
description?: string;
|
||||
domains?: string[];
|
||||
targets?: Array<{ host: string; port: number }>;
|
||||
routeRefs?: string[];
|
||||
}>(async (statePartArg, dataArg, actionContext): Promise<ITargetProfilesState> => {
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_CreateTargetProfile
|
||||
>('/typedrequest', 'createTargetProfile');
|
||||
const response = await request.fire({
|
||||
identity: context.identity!,
|
||||
name: dataArg.name,
|
||||
description: dataArg.description,
|
||||
domains: dataArg.domains,
|
||||
targets: dataArg.targets,
|
||||
routeRefs: dataArg.routeRefs,
|
||||
});
|
||||
if (!response.success) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: response.message || 'Failed to create target profile',
|
||||
};
|
||||
}
|
||||
return await actionContext!.dispatch(fetchTargetProfilesAction, null);
|
||||
} catch (error: unknown) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: error instanceof Error ? error.message : 'Failed to create target profile',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const updateTargetProfileAction = targetProfilesStatePart.createAction<{
|
||||
id: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
domains?: string[];
|
||||
targets?: Array<{ host: string; port: number }>;
|
||||
routeRefs?: string[];
|
||||
}>(async (statePartArg, dataArg, actionContext): Promise<ITargetProfilesState> => {
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_UpdateTargetProfile
|
||||
>('/typedrequest', 'updateTargetProfile');
|
||||
const response = await request.fire({
|
||||
identity: context.identity!,
|
||||
id: dataArg.id,
|
||||
name: dataArg.name,
|
||||
description: dataArg.description,
|
||||
domains: dataArg.domains,
|
||||
targets: dataArg.targets,
|
||||
routeRefs: dataArg.routeRefs,
|
||||
});
|
||||
if (!response.success) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: response.message || 'Failed to update target profile',
|
||||
};
|
||||
}
|
||||
return await actionContext!.dispatch(fetchTargetProfilesAction, null);
|
||||
} catch (error: unknown) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: error instanceof Error ? error.message : 'Failed to update target profile',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteTargetProfileAction = targetProfilesStatePart.createAction<{
|
||||
id: string;
|
||||
force?: boolean;
|
||||
}>(async (statePartArg, dataArg, actionContext): Promise<ITargetProfilesState> => {
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_DeleteTargetProfile
|
||||
>('/typedrequest', 'deleteTargetProfile');
|
||||
const response = await request.fire({
|
||||
identity: context.identity!,
|
||||
id: dataArg.id,
|
||||
force: dataArg.force,
|
||||
});
|
||||
if (!response.success) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: response.message || 'Failed to delete target profile',
|
||||
};
|
||||
}
|
||||
return await actionContext!.dispatch(fetchTargetProfilesAction, null);
|
||||
} catch (error: unknown) {
|
||||
return {
|
||||
...statePartArg.getState()!,
|
||||
error: error instanceof Error ? error.message : 'Failed to delete target profile',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Source Profiles & Network Targets State
|
||||
// ============================================================================
|
||||
|
||||
export interface IProfilesTargetsState {
|
||||
profiles: interfaces.data.ISecurityProfile[];
|
||||
profiles: interfaces.data.ISourceProfile[];
|
||||
targets: interfaces.data.INetworkTarget[];
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
@@ -1182,7 +1345,7 @@ export const profilesTargetsStatePart = await appState.getStatePart<IProfilesTar
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Security Profiles & Network Targets Actions
|
||||
// Source Profiles & Network Targets Actions
|
||||
// ============================================================================
|
||||
|
||||
export const fetchProfilesAndTargetsAction = profilesTargetsStatePart.createAction(
|
||||
@@ -1193,8 +1356,8 @@ export const fetchProfilesAndTargetsAction = profilesTargetsStatePart.createActi
|
||||
|
||||
try {
|
||||
const profilesRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_GetSecurityProfiles
|
||||
>('/typedrequest', 'getSecurityProfiles');
|
||||
interfaces.requests.IReq_GetSourceProfiles
|
||||
>('/typedrequest', 'getSourceProfiles');
|
||||
|
||||
const targetsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_GetNetworkTargets
|
||||
@@ -1231,8 +1394,8 @@ export const createProfileAction = profilesTargetsStatePart.createAction<{
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_CreateSecurityProfile
|
||||
>('/typedrequest', 'createSecurityProfile');
|
||||
interfaces.requests.IReq_CreateSourceProfile
|
||||
>('/typedrequest', 'createSourceProfile');
|
||||
await request.fire({
|
||||
identity: context.identity!,
|
||||
name: dataArg.name,
|
||||
@@ -1259,8 +1422,8 @@ export const updateProfileAction = profilesTargetsStatePart.createAction<{
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_UpdateSecurityProfile
|
||||
>('/typedrequest', 'updateSecurityProfile');
|
||||
interfaces.requests.IReq_UpdateSourceProfile
|
||||
>('/typedrequest', 'updateSourceProfile');
|
||||
await request.fire({
|
||||
identity: context.identity!,
|
||||
id: dataArg.id,
|
||||
@@ -1285,8 +1448,8 @@ export const deleteProfileAction = profilesTargetsStatePart.createAction<{
|
||||
const context = getActionContext();
|
||||
try {
|
||||
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
||||
interfaces.requests.IReq_DeleteSecurityProfile
|
||||
>('/typedrequest', 'deleteSecurityProfile');
|
||||
interfaces.requests.IReq_DeleteSourceProfile
|
||||
>('/typedrequest', 'deleteSourceProfile');
|
||||
const response = await request.fire({
|
||||
identity: context.identity!,
|
||||
id: dataArg.id,
|
||||
|
||||
Reference in New Issue
Block a user