From 2ee7d69f8076661c1e7286af7b4c7bc3c3767d6b Mon Sep 17 00:00:00 2001 From: braginini Date: Fri, 23 Sep 2022 18:16:24 +0200 Subject: [PATCH] Add UserInfo to PeerInfo --- management/server/account.go | 3 +- management/server/account_test.go | 2 +- management/server/http/peers.go | 63 ++++++++++--------- management/server/http/users.go | 4 +- management/server/mock_server/account_mock.go | 2 +- management/server/peer.go | 44 +++++++++++++ management/server/user.go | 20 +++--- 7 files changed, 98 insertions(+), 40 deletions(-) diff --git a/management/server/account.go b/management/server/account.go index 5ee127cc7..47b1e7393 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -47,6 +47,7 @@ type AccountManager interface { IsUserAdmin(claims jwtclaims.AuthorizationClaims) (bool, error) AccountExists(accountId string) (*bool, error) GetPeer(peerKey string) (*Peer, error) + GetPeers(accountID string) ([]*PeerInfo, error) MarkPeerConnected(peerKey string, connected bool) error RenamePeer(accountId string, peerKey string, newName string) (*Peer, error) DeletePeer(accountId string, peerKey string) (*Peer, error) @@ -57,7 +58,7 @@ type AccountManager interface { AddPeer(setupKey string, userId string, peer *Peer) (*Peer, error) UpdatePeerMeta(peerKey string, meta PeerSystemMeta) error UpdatePeerSSHKey(peerKey string, sshKey string) error - GetUsersFromAccount(accountId string) ([]*UserInfo, error) + GetUsers(accountId string) ([]*UserInfo, error) GetGroup(accountId, groupID string) (*Group, error) SaveGroup(accountId string, group *Group) error UpdateGroup(accountID string, groupID string, operations []GroupUpdateOperation) (*Group, error) diff --git a/management/server/account_test.go b/management/server/account_test.go index 1f05324cd..ea7e70a13 100644 --- a/management/server/account_test.go +++ b/management/server/account_test.go @@ -847,7 +847,7 @@ func TestGetUsersFromAccount(t *testing.T) { account.Users[user.Id] = user } - userInfos, err := manager.GetUsersFromAccount(accountId) + userInfos, err := manager.GetUsers(accountId) if err != nil { t.Fatal(err) } diff --git a/management/server/http/peers.go b/management/server/http/peers.go index d78921a6e..c49a35e04 100644 --- a/management/server/http/peers.go +++ b/management/server/http/peers.go @@ -11,7 +11,7 @@ import ( "net/http" ) -//Peers is a handler that returns peers of the account +// Peers is a handler that returns peers of the account type Peers struct { accountManager server.AccountManager authAudience string @@ -42,7 +42,7 @@ func (h *Peers) updatePeer(account *server.Account, peer *server.Peer, w http.Re http.Redirect(w, r, "/", http.StatusInternalServerError) return } - writeJSONObject(w, toPeerResponse(peer, account)) + writeJSONObject(w, toPeerResponse(&server.PeerInfo{Peer: peer}, account)) } func (h *Peers) deletePeer(accountId string, peer *server.Peer, w http.ResponseWriter, r *http.Request) { @@ -83,7 +83,7 @@ func (h *Peers) HandlePeer(w http.ResponseWriter, r *http.Request) { h.updatePeer(account, peer, w, r) return case http.MethodGet: - writeJSONObject(w, toPeerResponse(peer, account)) + writeJSONObject(w, toPeerResponse(&server.PeerInfo{Peer: peer}, account)) return default: @@ -93,27 +93,34 @@ func (h *Peers) HandlePeer(w http.ResponseWriter, r *http.Request) { } func (h *Peers) GetPeers(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r) - if err != nil { - log.Error(err) - http.Redirect(w, r, "/", http.StatusInternalServerError) - return - } - respBody := []*api.Peer{} - for _, peer := range account.Peers { - respBody = append(respBody, toPeerResponse(peer, account)) - } - writeJSONObject(w, respBody) - return - default: + if r.Method != http.MethodGet { http.Error(w, "", http.StatusNotFound) } + + account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r) + if err != nil { + log.Error(err) + http.Redirect(w, r, "/", http.StatusInternalServerError) + return + } + + peers, err := h.accountManager.GetPeers(account.Id) + if err != nil { + log.Error(err) + http.Redirect(w, r, "/", http.StatusInternalServerError) + return + } + + respBody := []*api.Peer{} + for _, peer := range peers { + respBody = append(respBody, toPeerResponse(peer, account)) + } + writeJSONObject(w, respBody) + return } -func toPeerResponse(peer *server.Peer, account *server.Account) *api.Peer { +func toPeerResponse(peer *server.PeerInfo, account *server.Account) *api.Peer { var groupsInfo []api.GroupMinimum groupsChecked := make(map[string]struct{}) for _, group := range account.Groups { @@ -123,7 +130,7 @@ func toPeerResponse(peer *server.Peer, account *server.Account) *api.Peer { } groupsChecked[group.ID] = struct{}{} for _, pk := range group.Peers { - if pk == peer.Key { + if pk == peer.Peer.Key { info := api.GroupMinimum{ Id: group.ID, Name: group.Name, @@ -135,14 +142,14 @@ func toPeerResponse(peer *server.Peer, account *server.Account) *api.Peer { } } return &api.Peer{ - Id: peer.IP.String(), - Name: peer.Name, - Ip: peer.IP.String(), - Connected: peer.Status.Connected, - LastSeen: peer.Status.LastSeen, - Os: fmt.Sprintf("%s %s", peer.Meta.OS, peer.Meta.Core), - Version: peer.Meta.WtVersion, + Id: peer.Peer.IP.String(), + Name: peer.Peer.Name, + Ip: peer.Peer.IP.String(), + Connected: peer.Peer.Status.Connected, + LastSeen: peer.Peer.Status.LastSeen, + Os: fmt.Sprintf("%s %s", peer.Peer.Meta.OS, peer.Peer.Meta.Core), + Version: peer.Peer.Meta.WtVersion, Groups: groupsInfo, - SshEnabled: peer.SSHEnabled, + SshEnabled: peer.Peer.SSHEnabled, } } diff --git a/management/server/http/users.go b/management/server/http/users.go index 83b253824..9a75b0788 100644 --- a/management/server/http/users.go +++ b/management/server/http/users.go @@ -92,9 +92,11 @@ func (h *UserHandler) GetUsers(w http.ResponseWriter, r *http.Request) { account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r) if err != nil { log.Error(err) + http.Redirect(w, r, "/", http.StatusInternalServerError) + return } - data, err := h.accountManager.GetUsersFromAccount(account.Id) + data, err := h.accountManager.GetUsers(account.Id) if err != nil { log.Error(err) http.Redirect(w, r, "/", http.StatusInternalServerError) diff --git a/management/server/mock_server/account_mock.go b/management/server/mock_server/account_mock.go index 501567c99..248710a7d 100644 --- a/management/server/mock_server/account_mock.go +++ b/management/server/mock_server/account_mock.go @@ -60,7 +60,7 @@ func (am *MockAccountManager) GetUsersFromAccount(accountID string) ([]*server.U if am.GetUsersFromAccountFunc != nil { return am.GetUsersFromAccountFunc(accountID) } - return nil, status.Errorf(codes.Unimplemented, "method GetUsersFromAccount is not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetUsers is not implemented") } // GetOrCreateAccountByUser mock implementation of GetOrCreateAccountByUser from server.AccountManager interface diff --git a/management/server/peer.go b/management/server/peer.go index 615137f79..438272b28 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -31,6 +31,12 @@ type PeerStatus struct { Connected bool } +// PeerInfo is a composition of Peer and additional UserInfo +type PeerInfo struct { + Peer *Peer + UserInfo *UserInfo +} + // Peer represents a machine connected to the network. // The Peer is a Wireguard peer identified by a public key type Peer struct { @@ -68,6 +74,44 @@ func (p *Peer) Copy() *Peer { } } +// GetPeers returns a list of Peers belonging to the specified account +func (am *DefaultAccountManager) GetPeers(accountID string) ([]*PeerInfo, error) { + am.mux.Lock() + defer am.mux.Unlock() + + account, err := am.Store.GetAccount(accountID) + if err != nil { + return nil, status.Errorf(codes.NotFound, "account not found") + } + + users, err := am.getUsersInfos(account) + if err != nil { + return nil, err + } + + var userMap = make(map[string]*UserInfo) + for _, user := range users { + userMap[user.ID] = user + } + + var peerInfos []*PeerInfo + for _, peer := range account.Peers { + if peer.UserID == "" { + peerInfos = append(peerInfos, &PeerInfo{ + Peer: peer, + UserInfo: nil, + }) + } else { + peerInfos = append(peerInfos, &PeerInfo{ + Peer: peer.Copy(), + UserInfo: userMap[peer.UserID], + }) + } + } + + return peerInfos, nil +} + // GetPeer returns a peer from a Store func (am *DefaultAccountManager) GetPeer(peerKey string) (*Peer, error) { am.mux.Lock() diff --git a/management/server/user.go b/management/server/user.go index 391debfb8..f68828058 100644 --- a/management/server/user.go +++ b/management/server/user.go @@ -207,16 +207,11 @@ func (am *DefaultAccountManager) IsUserAdmin(claims jwtclaims.AuthorizationClaim return user.Role == UserRoleAdmin, nil } -// GetUsersFromAccount performs a batched request for users from IDP by account ID -func (am *DefaultAccountManager) GetUsersFromAccount(accountID string) ([]*UserInfo, error) { - account, err := am.GetAccountById(accountID) - if err != nil { - return nil, err - } - +func (am *DefaultAccountManager) getUsersInfos(account *Account) ([]*UserInfo, error) { + var err error queriedUsers := make([]*idp.UserData, 0) if !isNil(am.idpManager) { - queriedUsers, err = am.lookupCache(account.Users, accountID) + queriedUsers, err = am.lookupCache(account.Users, account.Id) if err != nil { return nil, err } @@ -249,3 +244,12 @@ func (am *DefaultAccountManager) GetUsersFromAccount(accountID string) ([]*UserI return userInfos, nil } + +// GetUsers performs a batched request for users from IDP by account ID +func (am *DefaultAccountManager) GetUsers(accountID string) ([]*UserInfo, error) { + account, err := am.GetAccountById(accountID) + if err != nil { + return nil, err + } + return am.getUsersInfos(account) +}