Skip to content

Commit

Permalink
Support Auto Groups when updating setup keys (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
braginini authored Sep 13, 2022
1 parent 521df65 commit f389862
Show file tree
Hide file tree
Showing 12 changed files with 702 additions and 292 deletions.
2 changes: 1 addition & 1 deletion src/components/PeerUpdate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ const PeerUpdate = () => {
) : (
<Form.Item
name="name"
label="Update Name"
label="Name"
rules={[{
required: true,
message: 'Please add a new name for this peer',
Expand Down
471 changes: 378 additions & 93 deletions src/components/SetupKeyNew.tsx

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/store/rule/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export function* saveRule(action: ReturnType<typeof actions.saveRule.request>):
})
))


const resGroups = (responsesGroup as ApiResponse<Rule>[]).filter(r => r.statusCode === 200).map(r => (r.body as Group))

const currentGroups = [...(yield select(state => state.group.data)) as Rule[]]
Expand Down
25 changes: 8 additions & 17 deletions src/store/setup-key/actions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ActionType, createAction, createAsyncAction } from 'typesafe-actions';
import {SetupKey, SetupKeyRevoke} from './types';
import {SetupKey, SetupKeyToSave} from './types';
import {
ApiError,
ChangeResponse,
CreateResponse,
DeleteResponse,
RequestPayload
Expand All @@ -15,12 +14,13 @@ const actions = {
'GET_SETUP_KEYS_FAILURE',
)<RequestPayload<null>, SetupKey[], ApiError>(),

createSetupKey: createAsyncAction(
'CREATE_SETUP_KEY_REQUEST',
'CREATE_SETUP_KEY_SUCCESS',
'CREATE_SETUP_KEY_FAILURE',
)<RequestPayload<SetupKey>, CreateResponse<SetupKey | null>, CreateResponse<SetupKey | null>>(),
setCreateSetupKey: createAction('SET_CREATE_SETUP_KEY')<CreateResponse<SetupKey | null>>(),
saveSetupKey: createAsyncAction(
'SAVE_SETUP_KEY_REQUEST',
'SAVE_SETUP_KEY_SUCCESS',
'SAVE_SETUP_KEY_FAILURE',
)<RequestPayload<SetupKeyToSave>, CreateResponse<SetupKey | null>, CreateResponse<SetupKey | null>>(),
setSavedSetupKey: createAction('SET_SAVE_SETUP_KEY')<CreateResponse<SetupKey | null>>(),
resetSavedSetupKey: createAction('RESET_SAVE_SETUP_KEY')<null>(),

deleteSetupKey: createAsyncAction(
'DELETE_SETUP_KEY_REQUEST',
Expand All @@ -30,15 +30,6 @@ const actions = {
setDeleteSetupKey: createAction('SET_DELETE_SETUP_KEY')<DeleteResponse<string | null>>(),
resetDeletedSetupKey: createAction('RESET_DELETE_SETUP_KEY')<null>(),

revokeSetupKey: createAsyncAction(
'REVOKE_SETUP_KEY_REQUEST',
'REVOKE_SETUP_KEY_SUCCESS',
'REVOKE_SETUP_KEY_FAILURE'
)<RequestPayload<SetupKeyRevoke>, ChangeResponse<SetupKey | null>, ChangeResponse<SetupKey | null>>(),
setRevokeSetupKey: createAction('SET_REVOKED_SETUP_KEY')<ChangeResponse<SetupKey | null>>(),
resetRevokedSetupKey: createAction('RESET_REVOKED_SETUP_KEY')<null>(),


removeSetupKey: createAction('REMOVE_SETUP_KEY')<string>(),
setSetupKey: createAction('SET_SETUP_KEY')<SetupKey>(),
setSetupNewKeyVisible: createAction('SET_SETUP_NEW_KEY_VISIBLE')<boolean>()
Expand Down
25 changes: 9 additions & 16 deletions src/store/setup-key/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type StateType = Readonly<{
saving: boolean;
deletedSetupKey: DeleteResponse<string | null>;
revokedSetupKey: ChangeResponse<SetupKey | null>;
createdSetupKey: CreateResponse<SetupKey | null>;
savedSetupKey: CreateResponse<SetupKey | null>;
setupNewKeyVisible: boolean
}>;

Expand All @@ -36,7 +36,7 @@ const initialState: StateType = {
error: null,
data : null
},
createdSetupKey: <CreateResponse<SetupKey | null>>{
savedSetupKey: <CreateResponse<SetupKey | null>>{
loading: false,
success: false,
failure: false,
Expand Down Expand Up @@ -75,18 +75,12 @@ const deletedSetupKey = createReducer<DeleteResponse<string | null>, ActionTypes
.handleAction(actions.setDeleteSetupKey, (store, action) => action.payload)
.handleAction(actions.resetDeletedSetupKey, (store, action) => initialState.deletedSetupKey);

const revokedSetupKey = createReducer<ChangeResponse<SetupKey | null>, ActionTypes>(initialState.revokedSetupKey)
.handleAction(actions.revokeSetupKey.request, () => initialState.revokedSetupKey)
.handleAction(actions.revokeSetupKey.success, (store, action) => action.payload)
.handleAction(actions.revokeSetupKey.failure, (store, action) => action.payload)
.handleAction(actions.setRevokeSetupKey, (store, action) => action.payload)
.handleAction(actions.resetRevokedSetupKey, () => initialState.revokedSetupKey)

const createdSetupKey = createReducer<CreateResponse<SetupKey | null>, ActionTypes>(initialState.createdSetupKey)
.handleAction(actions.createSetupKey.request, () => initialState.createdSetupKey)
.handleAction(actions.createSetupKey.success, (store, action) => action.payload)
.handleAction(actions.createSetupKey.failure, (store, action) => action.payload)
.handleAction(actions.setCreateSetupKey, (store, action) => action.payload)
const savedSetupKey = createReducer<CreateResponse<SetupKey | null>, ActionTypes>(initialState.savedSetupKey)
.handleAction(actions.saveSetupKey.request, () => initialState.savedSetupKey)
.handleAction(actions.saveSetupKey.success, (store, action) => action.payload)
.handleAction(actions.saveSetupKey.failure, (store, action) => action.payload)
.handleAction(actions.setSavedSetupKey, (store, action) => action.payload)
.handleAction(actions.resetSavedSetupKey, () => initialState.savedSetupKey)

const setupNewKeyVisible = createReducer<boolean, ActionTypes>(initialState.setupNewKeyVisible)
.handleAction(actions.setSetupNewKeyVisible, (store, action) => action.payload)
Expand All @@ -98,7 +92,6 @@ export default combineReducers({
failed,
saving,
deletedSetupKey,
revokedSetupKey,
createdSetupKey,
savedSetupKey: savedSetupKey,
setupNewKeyVisible
});
116 changes: 59 additions & 57 deletions src/store/setup-key/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,94 @@
import {all, call, put, select, takeLatest} from 'redux-saga/effects';
import {ApiError, ApiResponse, ChangeResponse, CreateResponse, DeleteResponse} from '../../services/api-client/types';
import {SetupKey, SetupKeyRevoke} from './types'
import {ApiError, ApiResponse, CreateResponse, DeleteResponse} from '../../services/api-client/types';
import {SetupKey, SetupKeyToSave} from './types'
import service from './service';
import actions from './actions';
import serviceGroup from "../group/service";
import {Group} from "../group/types";
import {actions as groupActions} from "../group";

export function* getSetupKeys(action: ReturnType<typeof actions.getSetupKeys.request>): Generator {
try {
const effect = yield call(service.getSetupKeys, action.payload);
const response = effect as ApiResponse<SetupKey[]>;

yield put(actions.getSetupKeys.success(response.body));
yield put(actions.getSetupKeys.success(response.body.map(k => {
// always set auto_groups even if absent (avoid null)
if (k.auto_groups) {
return k
}
return {...k, auto_groups: []}
})));
} catch (err) {
yield put(actions.getSetupKeys.failure(err as ApiError));
}
}

export function* setCreateSetupKey(action: ReturnType<typeof actions.setCreateSetupKey>): Generator {
yield put(actions.setCreateSetupKey(action.payload))
export function* setCreateSetupKey(action: ReturnType<typeof actions.setSavedSetupKey>): Generator {
yield put(actions.setSavedSetupKey(action.payload))
}

export function* createSetupKey(action: ReturnType<typeof actions.createSetupKey.request>): Generator {
export function* saveSetupKey(action: ReturnType<typeof actions.saveSetupKey.request>): Generator {
try {
yield put(actions.setCreateSetupKey({
yield put(actions.setSavedSetupKey({
loading: true,
success: false,
failure: false,
error: null,
data: null
} as CreateResponse<SetupKey | null>))

const effect = yield call(service.createSetupKey, action.payload);
const keyToSave = action.payload.payload

let groupsToCreate = keyToSave.groupsToCreate
if (!groupsToCreate) {
groupsToCreate = []
}

// first, create groups that were newly added by user
const responsesGroup = yield all(groupsToCreate.map(g => call(serviceGroup.createGroup, {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: { name: g }
})
))

const resGroups = (responsesGroup as ApiResponse<Group>[]).filter(r => r.statusCode === 200).map(g => (g.body as Group)).map(g => g.id)
const newGroups = [...keyToSave.auto_groups, ...resGroups]
let effect
if (!keyToSave.id) {
effect = yield call(service.createSetupKey, {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: {
name: keyToSave.name,
auto_groups: newGroups,
type: keyToSave.type
} as SetupKeyToSave
});
} else {
effect = yield call(service.editSetupKey, {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: {
id: keyToSave.id,
name: keyToSave.name,
revoked: keyToSave.revoked,
auto_groups: newGroups,
} as SetupKeyToSave
});
}
const response = effect as ApiResponse<SetupKey>;

yield put(actions.createSetupKey.success({
yield put(actions.saveSetupKey.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body
} as CreateResponse<SetupKey | null>));

const setupKeys = [...(yield select(state => state.setupKey.data)) as SetupKey[]]
setupKeys.unshift(response.body)
yield put(actions.getSetupKeys.success(setupKeys));
yield put(groupActions.getGroups.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null }));
yield put(actions.getSetupKeys.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null }));
} catch (err) {
yield put(actions.createSetupKey.failure({
yield put(actions.saveSetupKey.failure({
loading: false,
success: false,
failure: false,
Expand Down Expand Up @@ -92,53 +136,11 @@ export function* deleteSetupKey(action: ReturnType<typeof actions.deleteSetupKey
}
}

export function* revokeSetupKey(action: ReturnType<typeof actions.revokeSetupKey.request>): Generator {
try {
yield put(actions.setRevokeSetupKey({
loading: true,
success: false,
failure: false,
error: null,
data: null
} as ChangeResponse<SetupKey | null>))

const effect = yield call(service.revokeSetupKey, action.payload);
const response = effect as ApiResponse<SetupKey>;

yield put(actions.revokeSetupKey.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body
} as ChangeResponse<SetupKey | null>));

const setupKeys = [...(yield select(state => state.setupKey.data)) as SetupKey[]]
let setupKey = setupKeys.find(s => s.id === response.body.id) as SetupKey
if (setupKey) {
setupKey.revoked = response.body.revoked
setupKey.valid = response.body.valid
setupKey.state = response.body.state
setupKey.expires = response.body.expires
}
yield put(actions.getSetupKeys.success(setupKeys));
} catch (err) {
yield put(actions.createSetupKey.failure({
loading: false,
success: false,
failure: false,
error: err as ApiError,
data: null
} as CreateResponse<SetupKey | null>));
}
}

export default function* sagas(): Generator {
yield all([
takeLatest(actions.getSetupKeys.request, getSetupKeys),
takeLatest(actions.createSetupKey.request, createSetupKey),
takeLatest(actions.deleteSetupKey.request, deleteSetupKey),
takeLatest(actions.revokeSetupKey.request, revokeSetupKey)
takeLatest(actions.saveSetupKey.request, saveSetupKey),
takeLatest(actions.deleteSetupKey.request, deleteSetupKey)
]);
}

21 changes: 9 additions & 12 deletions src/store/setup-key/service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ApiResponse, RequestPayload} from '../../services/api-client/types';
import { apiClient } from '../../services/api-client';
import {SetupKey, SetupKeyNew, SetupKeyRevoke} from './types';
import {SetupKey, SetupKeyToSave} from './types';

export default {
async getSetupKeys(payload:RequestPayload<null>): Promise<ApiResponse<SetupKey[]>> {
Expand All @@ -15,21 +15,18 @@ export default {
payload
);
},
async revokeSetupKey(payload:RequestPayload<SetupKeyRevoke>): Promise<ApiResponse<SetupKey>> {
return apiClient.put<SetupKey>(
`/api/setup-keys/` + payload.payload.id,
async createSetupKey(payload:RequestPayload<SetupKeyToSave>): Promise<ApiResponse<SetupKey>> {
return apiClient.post<SetupKey>(
`/api/setup-keys`,
payload
);
},
async renameSetupKey(payload:RequestPayload<any>): Promise<ApiResponse<SetupKey>> {
async editSetupKey(payload:RequestPayload<SetupKeyToSave>): Promise<ApiResponse<SetupKey>> {
const id = payload.payload.id
// @ts-ignore
delete payload.payload.id
return apiClient.put<SetupKey>(
`/api/setup-keys/` + payload.payload.id,
payload
);
},
async createSetupKey(payload:RequestPayload<SetupKey>): Promise<ApiResponse<SetupKey>> {
return apiClient.post<SetupKey>(
`/api/setup-keys`,
`/api/setup-keys/${id}`,
payload
);
},
Expand Down
15 changes: 6 additions & 9 deletions src/store/setup-key/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {Group} from "../group/types";

export interface SetupKey {
expires: string;
id: string;
Expand All @@ -9,15 +11,10 @@ export interface SetupKey {
type: string;
used_times: number;
valid: boolean;
auto_groups: string[]
}

export interface SetupKeyNew {
id: string;
name: string;
type: string;
}

export interface SetupKeyRevoke {
id: string;
revoked: boolean;
export interface SetupKeyToSave extends SetupKey
{
groupsToCreate: string[]
}
2 changes: 0 additions & 2 deletions src/utils/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export const transformGroupedDataTable = (routes:Route[],peerIPToName:PeerIPToNa
}
})
let groupDataTableRoutes = transformDataTable(listedRoutes,peerIPToName)
console.log(groupDataTableRoutes.length)
groupedRoutes.push({
key: p.toString(),
network_id: lastRoute!.network_id,
Expand All @@ -78,6 +77,5 @@ export const transformGroupedDataTable = (routes:Route[],peerIPToName:PeerIPToNa
groupedRoutes: groupDataTableRoutes,
})
})
console.log(groupedRoutes)
return groupedRoutes
}
2 changes: 1 addition & 1 deletion src/views/AccessControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const AccessControl = () => {
if (savedRule.loading) {
message.loading({ content: 'Saving...', key: saveKey, duration: 0, style: styleNotification })
} else if (savedRule.success) {
message.success({ content: 'Rule has been successfully updated.', key: saveKey, duration: 2, style: styleNotification });
message.success({ content: 'Rule has been successfully saved.', key: saveKey, duration: 2, style: styleNotification });
dispatch(ruleActions.setSetupNewRuleVisible(false))
dispatch(ruleActions.setSavedRule({ ...savedRule, success: false }))
dispatch(ruleActions.resetSavedRule(null))
Expand Down
6 changes: 3 additions & 3 deletions src/views/Peers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const Peers = () => {

const [textToSearch, setTextToSearch] = useState('');
const [optionOnOff, setOptionOnOff] = useState('all');
const [pageSize, setPageSize] = useState(5);
const [pageSize, setPageSize] = useState(10);
const [dataTable, setDataTable] = useState([] as PeerDataTable[]);
const [peerToAction, setPeerToAction] = useState(null as PeerDataTable | null);

Expand All @@ -82,7 +82,7 @@ export const Peers = () => {
const itemsMenuAction = [
{
key: "view",
label: (<Button type="text" block onClick={() => onClickViewRule()}>View</Button>)
label: (<Button type="text" block onClick={() => onClickViewPeer()}>View</Button>)
},
{
key: "delete",
Expand Down Expand Up @@ -300,7 +300,7 @@ export const Peers = () => {

}

const onClickViewRule = () => {
const onClickViewPeer = () => {
dispatch(peerActions.setUpdateGroupsVisible(true))
dispatch(peerActions.setPeer(peerToAction as Peer))
}
Expand Down
Loading

0 comments on commit f389862

Please sign in to comment.