From 34c144facb24e78e25cb33d764e778b86e48e1b3 Mon Sep 17 00:00:00 2001 From: Pascal Fischer Date: Wed, 29 Nov 2023 16:13:49 +0100 Subject: [PATCH 1/2] add support for peer approval --- src/store/account/types.ts | 4 +++ src/store/peer/types.ts | 3 +- src/views/Activity.tsx | 4 +++ src/views/Peers.tsx | 72 +++++++++++++++++++++++++++++++++++--- src/views/Settings.tsx | 62 ++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 6 deletions(-) diff --git a/src/store/account/types.ts b/src/store/account/types.ts index aa0d007c..b2a71615 100644 --- a/src/store/account/types.ts +++ b/src/store/account/types.ts @@ -8,6 +8,9 @@ export interface Account { jwt_groups_enabled: boolean; groups_propagation_enabled: boolean; jwt_groups_claim_name: string; + extra: { + peer_approval_enabled: boolean; + } }; } @@ -17,4 +20,5 @@ export interface FormAccount extends Account { groups_propagation_enabled: boolean; jwt_groups_claim_name: string; peer_login_expiration_formatted: ExpiresInValue; + peer_approval_enabled: boolean; } \ No newline at end of file diff --git a/src/store/peer/types.ts b/src/store/peer/types.ts index af48b46f..3f26b3d6 100644 --- a/src/store/peer/types.ts +++ b/src/store/peer/types.ts @@ -16,7 +16,8 @@ export interface Peer { dns_label: string, last_login: string, login_expired: boolean, - login_expiration_enabled: boolean + login_expiration_enabled: boolean, + approval_required: boolean } export interface FormPeer extends Peer { diff --git a/src/views/Activity.tsx b/src/views/Activity.tsx index 1ee49544..12f0373e 100644 --- a/src/views/Activity.tsx +++ b/src/views/Activity.tsx @@ -338,6 +338,8 @@ export const Activity = () => { case "peer.login.expiration.enable": case "user.peer.login": case "peer.login.expire": + case "peer.approve": + case "peer.approval.revoke": return renderMultiRowSpan(event.meta.fqdn, event.meta.ip); case "route.add": case "route.delete": @@ -373,6 +375,8 @@ export const Activity = () => { case "account.setting.peer.login.expiration.enable": case "account.setting.peer.login.expiration.disable": case "account.setting.peer.login.expiration.update": + case "account.setting.peer.approval.enable": + case "account.setting.peer.approval.disable": case "integration.create": case "integration.update": case "integration.delete": diff --git a/src/views/Peers.tsx b/src/views/Peers.tsx index 7225929d..060e933c 100644 --- a/src/views/Peers.tsx +++ b/src/views/Peers.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { capitalize, formatOS, timeAgo } from "../utils/common"; +import {capitalize, formatOS, isLocalDev, isNetBirdHosted, timeAgo} from "../utils/common"; import { useDispatch, useSelector } from "react-redux"; import { RootState } from "typesafe-actions"; import { actions as peerActions } from "../store/peer"; @@ -79,6 +79,7 @@ export const Peers = () => { (state: RootState) => state.peer.updateGroupsVisible ); const users = useSelector((state: RootState) => state.user.data); + const account = useSelector((state: RootState) => state.account.data); const [addPeerModalOpen, setAddPeerModalOpen] = useState(false); const { oidcUser } = useOidcUser(); const [isAdmin, setIsAdmin] = useState(false); @@ -100,6 +101,7 @@ export const Peers = () => { const optionsOnOff = [ { label: "Online", value: "on" }, { label: "All", value: "all" }, + // ...((isNetBirdHosted() || isLocalDev()) && account[0].settings.extra.peer_approval_enabled ? [{ label: "Needs approval", value: "approval" }] : []), ]; const transformDataTable = (d: Peer[]): PeerDataTable[] => { @@ -291,6 +293,16 @@ export const Peers = () => { ); }) as Peer[]; + // switch (optionOnOff) { + // case "on": + // f = filter(f, (f: Peer) => f.connected); + // break; + // case "approval": + // f = filter(f, (f: Peer) => f.approval_required); + // break; + // default: + // break; + // } if (optionOnOff === "on") { f = filter(f, (f: Peer) => f.connected); } @@ -410,6 +422,36 @@ export const Peers = () => { }); }; + const showConfirmApprove = (record: PeerDataTable) => { + setPeerToAction(record); + + let content = ( + + Are you sure you want to approve this peer? + + ); + + let name = record ? record.name : ""; + confirmModal.confirm({ + icon: , + title: Approve peer {name}, + width: 600, + content: content, + onOk() { + record.approval_required = false + dispatch( + peerActions.updatePeer.request({ + getAccessTokenSilently: getTokenSilently, + payload: record, + }) + ); + }, + onCancel() { + setPeerToAction(null); + }, + }); + }; + const showConfirmEnableSSH = (record: PeerDataTable) => { confirmModal.confirm({ icon: , @@ -601,6 +643,19 @@ export const Peers = () => { "" ); + let approval = peer.approval_required ? ( + + + needs approval + + + ) : ( + "" + ); + const userEmail = users?.find((u) => u.id === peer.user_id)?.email; let expiry = !peer.login_expiration_enabled ? ( @@ -622,9 +677,9 @@ export const Peers = () => { {status} - {loginExpire} + {loginExpire} ); } @@ -643,11 +698,18 @@ export const Peers = () => { {userEmail} - - {expiry} {loginExpire} - + + {expiry} {loginExpire} + ); }; diff --git a/src/views/Settings.tsx b/src/views/Settings.tsx index c8dd1f83..efa9e98f 100644 --- a/src/views/Settings.tsx +++ b/src/views/Settings.tsx @@ -127,6 +127,8 @@ export const Settings = () => { const [formPeerExpirationEnabled, setFormPeerExpirationEnabled] = useState(true); + const [formPeerApprovalEnabled, setFormPeerApprovalEnabled] = + useState(false); const [jwtGroupsEnabled, setJwtGroupsEnabled] = useState(true); const [groupsPropagationEnabled, setGroupsPropagationEnabled] = useState(true); @@ -221,9 +223,11 @@ export const Settings = () => { jwt_groups_enabled: account.settings.jwt_groups_enabled, jwt_groups_claim_name: account.settings.jwt_groups_claim_name, groups_propagation_enabled: account.settings.groups_propagation_enabled, + peer_approval_enabled: account.settings.extra ? account.settings.extra.peer_approval_enabled : false, } as FormAccount; setFormAccount(fAccount); setFormPeerExpirationEnabled(fAccount.peer_login_expiration_enabled); + setFormPeerApprovalEnabled(fAccount.peer_approval_enabled); setJwtGroupsEnabled(fAccount.jwt_groups_enabled); setGroupsPropagationEnabled(fAccount.groups_propagation_enabled); setJwtGroupsClaimName(fAccount.jwt_groups_claim_name); @@ -394,6 +398,7 @@ export const Settings = () => { updatedAccount.data.settings.jwt_groups_claim_name, groups_propagation_enabled: updatedAccount.data.settings.groups_propagation_enabled, + peer_approval_enabled: updatedAccount.data.settings.extra.peer_approval_enabled } as FormAccount; setFormAccount(fAccount); } else if (updatedAccount.error) { @@ -428,6 +433,7 @@ export const Settings = () => { jwt_groups_enabled: jwtGroupsEnabled, jwt_groups_claim_name: jwtGroupsClaimName, groups_propagation_enabled: groupsPropagationEnabled, + peer_approval_enabled: formPeerApprovalEnabled, }); }) .catch((errorInfo) => { @@ -453,6 +459,9 @@ export const Settings = () => { jwt_groups_enabled: jwtGroupsEnabled, jwt_groups_claim_name: jwtGroupsClaimName, groups_propagation_enabled: groupsPropagationEnabled, + extra: { + peer_approval_enabled: values.peer_approval_enabled + } }, } as Account; }; @@ -624,6 +633,59 @@ export const Settings = () => {
+ {(isNetBirdHosted() || isLocalDev()) && +
+ { + setFormPeerApprovalEnabled(checked); + }} + size="small" + checked={formPeerApprovalEnabled} + /> +
+ + + Require peers to be approved by an administrator + +
+
+
}
Date: Mon, 4 Dec 2023 16:40:58 +0100 Subject: [PATCH 2/2] use gold color for tag --- src/views/Peers.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/Peers.tsx b/src/views/Peers.tsx index 569818da..a9aebaa4 100644 --- a/src/views/Peers.tsx +++ b/src/views/Peers.tsx @@ -645,9 +645,9 @@ export const Peers = () => { let approval = peer.approval_required ? ( - + needs approval