diff --git a/management/server/integrated_approval.go b/management/server/integrated_approval.go index 80e1a9ce2..34df7726a 100644 --- a/management/server/integrated_approval.go +++ b/management/server/integrated_approval.go @@ -20,6 +20,9 @@ import ( // Returns: // - error: An error if any occurred during the process, otherwise returns nil func (am *DefaultAccountManager) UpdateIntegratedApprovalGroups(accountID string, userID string, groups []string) error { + unlock := am.Store.AcquireAccountLock(accountID) + defer unlock() + ok, err := am.GroupValidation(accountID, groups) if err != nil { log.Debugf("error validating groups: %s", err.Error()) @@ -31,9 +34,6 @@ func (am *DefaultAccountManager) UpdateIntegratedApprovalGroups(accountID string return errors.New("invalid groups") } - unlock := am.Store.AcquireAccountLock(accountID) - defer unlock() - a, err := am.Store.GetAccountByUser(userID) if err != nil { return err @@ -48,6 +48,16 @@ func (am *DefaultAccountManager) UpdateIntegratedApprovalGroups(accountID string a.Settings.Extra = extra } extra.IntegratedApprovalGroups = groups + + am.cleanIntegratedApprovalFlag(a, groups) + err = am.updateFlags(a, groups) + if err != nil { + saveErr := am.Store.SaveAccount(a) + if saveErr != nil { + log.Errorf("failed to save account: %s", saveErr) + } + return err + } return am.Store.SaveAccount(a) } @@ -74,3 +84,49 @@ func (am *DefaultAccountManager) GroupValidation(accountId string, groups []stri return true, nil } + +// updateFlags set the requiresIntegratedApproval flag to true for all peers in the account what is part of the groups, but the peer not part of the already approved list in the edr db +func (am *DefaultAccountManager) updateFlags(a *Account, groups []string) error { + approvedPeers, err := am.integratedPeerValidator.ApprovedPeersList(a.Id) + if err != nil { + log.Errorf("failed to get approved peers list: %s", err) + return err + } + + for peerID, peer := range a.Peers { + peerGroups := a.GetPeerGroupsList(peerID) + if !isPeerAssignedToIntegratedApprovalGroup(peerGroups, groups) { + continue + } + + // set true only that case if not yet approved in the edr db + _, ok := approvedPeers[peerID] + if ok { + continue + } + peer.Status.RequiresIntegratedApproval = true + } + return nil +} + +// cleanIntegratedApprovalFlag set the requireIntegratedApproval flag to false for all peers in the account what is not part of the groups +func (am *DefaultAccountManager) cleanIntegratedApprovalFlag(a *Account, groups []string) { + for peerID, peer := range a.Peers { + peerGroups := a.GetPeerGroupsList(peerID) + if isPeerAssignedToIntegratedApprovalGroup(peerGroups, groups) { + continue + } + peer.Status.RequiresIntegratedApproval = false + } +} + +func isPeerAssignedToIntegratedApprovalGroup(peersGroup []string, integratedApprovalGroups []string) bool { + for _, peerGroup := range peersGroup { + for _, ig := range integratedApprovalGroups { + if ig == peerGroup { + return true + } + } + } + return false +} diff --git a/management/server/integrated_approval/interface.go b/management/server/integrated_approval/interface.go index be09d2669..21296eefb 100644 --- a/management/server/integrated_approval/interface.go +++ b/management/server/integrated_approval/interface.go @@ -8,6 +8,7 @@ import ( // IntegratedApproval interface exists to avoid the circle dependencies type IntegratedApproval interface { PreparePeer(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) *nbpeer.Peer - IsRequiresApproval(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) bool + IsRequiresApproval(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (bool, bool) + ApprovedPeersList(id string) (map[string]struct{}, error) Stop() } diff --git a/management/server/peer.go b/management/server/peer.go index b8ab3091d..a398de9d6 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -521,9 +521,10 @@ func (am *DefaultAccountManager) SyncPeer(sync PeerSync) (*nbpeer.Peer, *Network return nil, nil, status.Errorf(status.PermissionDenied, "peer login has expired, please log in once more") } - requiresApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra) - if peer.Status.RequiresApproval != requiresApproval { + requiresApproval, requiresIntegratedApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra) + if peer.Status.RequiresApproval != requiresApproval || peer.Status.RequiresIntegratedApproval != requiresIntegratedApproval { peer.Status.RequiresApproval = requiresApproval + peer.Status.RequiresIntegratedApproval = requiresIntegratedApproval err = am.Store.SaveAccount(account) if err != nil { return nil, nil, err @@ -596,8 +597,10 @@ func (am *DefaultAccountManager) LoginPeer(login PeerLogin) (*nbpeer.Peer, *Netw am.StoreEvent(login.UserID, peer.ID, account.Id, activity.UserLoggedInPeer, peer.EventMeta(am.GetDNSDomain())) } - isRequiresApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra) - if peer.Status.RequiresApproval != isRequiresApproval { + isRequiresApproval, isRequiresIntegratedApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra) + if peer.Status.RequiresApproval != isRequiresApproval || peer.Status.RequiresIntegratedApproval != isRequiresIntegratedApproval { + peer.Status.RequiresApproval = isRequiresApproval + peer.Status.RequiresIntegratedApproval = isRequiresIntegratedApproval shouldStoreAccount = true } diff --git a/management/server/peer/peer.go b/management/server/peer/peer.go index e62843180..c59a835e9 100644 --- a/management/server/peer/peer.go +++ b/management/server/peer/peer.go @@ -57,6 +57,8 @@ type PeerStatus struct { //nolint:revive LoginExpired bool // RequiresApproval indicates whether peer requires approval or not RequiresApproval bool + // RequiresIntegratedApproval indicates whether peer requires integrated approval or not + RequiresIntegratedApproval bool } // Location is a geo location information of a Peer based on public connection IP @@ -222,10 +224,11 @@ func (p *Peer) EventMeta(dnsDomain string) map[string]any { // Copy PeerStatus func (p *PeerStatus) Copy() *PeerStatus { return &PeerStatus{ - LastSeen: p.LastSeen, - Connected: p.Connected, - LoginExpired: p.LoginExpired, - RequiresApproval: p.RequiresApproval, + LastSeen: p.LastSeen, + Connected: p.Connected, + LoginExpired: p.LoginExpired, + RequiresApproval: p.RequiresApproval, + RequiresIntegratedApproval: p.RequiresIntegratedApproval, } }