Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Peers auto-tagging with the setup keys with predefined groups #75

Merged
merged 33 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f0bd8bc
Support new PUT request for SetupKeys endpoint
braginini Sep 10, 2022
cb320cb
Add SetupKey edit drawer
braginini Sep 10, 2022
a767fdd
Add SetupKey update drawer Form bindings
braginini Sep 10, 2022
a9d3b04
Add LastUsed and Expires fields
braginini Sep 11, 2022
41a1a45
Add Key status to the update view
braginini Sep 11, 2022
3b27a71
Distinguish new key and edit key
braginini Sep 11, 2022
e5ed077
Fix setup key type radio enabled mode
braginini Sep 11, 2022
a920029
Save setup key service
braginini Sep 11, 2022
aae9133
Refactor save setup key
braginini Sep 11, 2022
dc7d37d
Finalize update setup key
braginini Sep 11, 2022
a77d398
Remove unused revoke function
braginini Sep 11, 2022
d3069b2
Support new GroupMin response field
braginini Sep 12, 2022
bbf7a39
Fix AutoGroups display on SetupKey view
braginini Sep 12, 2022
19355de
Add groups loading to SetupKeys tab
braginini Sep 12, 2022
1154daa
Fix SetupKeyNew form groups assignment
braginini Sep 12, 2022
5cebd72
Add group creation on the SetupKey update
braginini Sep 12, 2022
4cfce3f
Fix revoke
braginini Sep 12, 2022
e0ee981
Don't allow invalid keys editing
braginini Sep 12, 2022
64d580b
Don't allow invalid keys editing
braginini Sep 12, 2022
48cca71
Use group.id intead of a full response from management
braginini Sep 12, 2022
a2e0578
Fix errors
braginini Sep 12, 2022
3dfea42
Reload groups when saving keys with new groups
braginini Sep 12, 2022
507102a
Fix potential NPE
braginini Sep 12, 2022
6a64921
Merge remote-tracking branch 'origin/main' into feature/put-setup-key
braginini Sep 13, 2022
1568881
Fix empty autogroups
braginini Sep 13, 2022
4566a34
Change Edit setup key to View
braginini Sep 13, 2022
4e5c2c5
Add groups count to SetupKeys table
braginini Sep 13, 2022
26fa229
If 0 groups don't render popup
braginini Sep 13, 2022
4bc07d7
Exclude group All when displaying groups in Update setup key
braginini Sep 13, 2022
e941686
Fix doc links and display count
braginini Sep 13, 2022
2cbf1d0
Fix NPE when no groups provided
braginini Sep 13, 2022
816a0e7
Fix revocation when no auto_groups present
braginini Sep 13, 2022
ebaa205
Remove routes console log messages
braginini Sep 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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