diff --git a/management/internals/modules/permissions/manager.go b/management/internals/modules/permissions/manager.go index 0cebc7dbc..5ec24bbce 100644 --- a/management/internals/modules/permissions/manager.go +++ b/management/internals/modules/permissions/manager.go @@ -23,7 +23,7 @@ import ( // AuthErrorHandler is called when an auth error occurs during permission validation. // If it returns true, the error is considered handled and the default error response is skipped. -type AuthErrorHandler func(w http.ResponseWriter, r *http.Request, err error) bool +type AuthErrorHandler func(w http.ResponseWriter, r *http.Request, userAuth *auth.UserAuth, err error) bool type Manager interface { WithPermission(module modules.Module, operation operations.Operation, handlerFunc func(w http.ResponseWriter, r *http.Request, auth *auth.UserAuth), authErrHandler ...AuthErrorHandler) http.HandlerFunc @@ -68,7 +68,7 @@ func (m *managerImpl) WithPermission( allowed, err := m.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, module, operation) if err != nil { - if onAuthErr != nil && onAuthErr(w, r, err) { + if onAuthErr != nil && onAuthErr(w, r, &userAuth, err) { return } log.WithContext(r.Context()).Errorf("failed to validate permissions for user %s on account %s: %v", userAuth.UserId, userAuth.AccountId, err) @@ -78,7 +78,7 @@ func (m *managerImpl) WithPermission( if !allowed { permErr := status.NewPermissionDeniedError() - if onAuthErr != nil && onAuthErr(w, r, permErr) { + if onAuthErr != nil && onAuthErr(w, r, &userAuth, permErr) { return } log.WithContext(r.Context()).Tracef("user %s on account %s is not allowed to %s in %s", userAuth.UserId, userAuth.AccountId, operation, module) diff --git a/management/server/account/manager.go b/management/server/account/manager.go index 45af63ae8..54d39cf7d 100644 --- a/management/server/account/manager.go +++ b/management/server/account/manager.go @@ -60,7 +60,7 @@ type Manager interface { GetUserByID(ctx context.Context, id string) (*types.User, error) GetUserFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (*types.User, error) ListUsers(ctx context.Context, accountID string) ([]*types.User, error) - GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error) + GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string, all bool) ([]*nbpeer.Peer, error) MarkPeerConnected(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string, syncTime time.Time) error DeletePeer(ctx context.Context, accountID, peerID, userID string) error UpdatePeer(ctx context.Context, accountID, userID string, p *nbpeer.Peer) (*nbpeer.Peer, error) diff --git a/management/server/http/handlers/accounts/accounts_handler.go b/management/server/http/handlers/accounts/accounts_handler.go index b14b0cc3d..b88368fdc 100644 --- a/management/server/http/handlers/accounts/accounts_handler.go +++ b/management/server/http/handlers/accounts/accounts_handler.go @@ -102,7 +102,7 @@ func (h *handler) validateNetworkRange(ctx context.Context, accountID, userID st } func (h *handler) validateCapacity(ctx context.Context, accountID, userID string, prefix netip.Prefix) error { - peers, err := h.accountManager.GetPeers(ctx, accountID, userID, "", "") + peers, err := h.accountManager.GetPeers(ctx, accountID, userID, "", "", true) if err != nil { return status.Errorf(status.Internal, "get peer count: %v", err) } diff --git a/management/server/http/handlers/groups/groups_handler.go b/management/server/http/handlers/groups/groups_handler.go index f04294a96..dc7130209 100644 --- a/management/server/http/handlers/groups/groups_handler.go +++ b/management/server/http/handlers/groups/groups_handler.go @@ -52,7 +52,7 @@ func (h *handler) getAllGroups(w http.ResponseWriter, r *http.Request, userAuth return } - accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "") + accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "", true) if err != nil { util.WriteError(r.Context(), err, w) return @@ -71,7 +71,7 @@ func (h *handler) getAllGroups(w http.ResponseWriter, r *http.Request, userAuth return } - accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "") + accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "", true) if err != nil { util.WriteError(r.Context(), err, w) return @@ -158,7 +158,7 @@ func (h *handler) updateGroup(w http.ResponseWriter, r *http.Request, userAuth * return } - accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "") + accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "", true) if err != nil { util.WriteError(r.Context(), err, w) return @@ -210,7 +210,7 @@ func (h *handler) createGroup(w http.ResponseWriter, r *http.Request, userAuth * return } - accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "") + accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "", true) if err != nil { util.WriteError(r.Context(), err, w) return @@ -256,7 +256,7 @@ func (h *handler) getGroup(w http.ResponseWriter, r *http.Request, userAuth *aut return } - accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "") + accountPeers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, "", "", true) if err != nil { util.WriteError(r.Context(), err, w) return diff --git a/management/server/http/handlers/peers/peers_handler.go b/management/server/http/handlers/peers/peers_handler.go index 06823c0f8..a8af9aa18 100644 --- a/management/server/http/handlers/peers/peers_handler.go +++ b/management/server/http/handlers/peers/peers_handler.go @@ -271,7 +271,7 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request, userAuth * nameFilter := r.URL.Query().Get("name") ipFilter := r.URL.Query().Get("ip") - peers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, nameFilter, ipFilter) + peers, err := h.accountManager.GetPeers(r.Context(), userAuth.AccountId, userAuth.UserId, nameFilter, ipFilter, true) if err != nil { util.WriteError(r.Context(), err, w) return diff --git a/management/server/http/handlers/users/users_handler.go b/management/server/http/handlers/users/users_handler.go index 09b506b67..b6ff9fa35 100644 --- a/management/server/http/handlers/users/users_handler.go +++ b/management/server/http/handlers/users/users_handler.go @@ -27,7 +27,7 @@ type handler struct { func AddEndpoints(accountManager account.Manager, router *mux.Router, permissionsManager permissions.Manager) { userHandler := newHandler(accountManager) - router.HandleFunc("/users", permissionsManager.WithPermission(modules.Users, operations.Read, userHandler.getAllUsers)).Methods("GET", "OPTIONS") + router.HandleFunc("/users", permissionsManager.WithPermission(modules.Users, operations.Read, userHandler.getAllUsers, userHandler.getOwnUser)).Methods("GET", "OPTIONS") router.HandleFunc("/users/current", permissionsManager.WithPermission(modules.Users, operations.Read, userHandler.getCurrentUser)).Methods("GET", "OPTIONS") router.HandleFunc("/users/{userId}", permissionsManager.WithPermission(modules.Users, operations.Update, userHandler.updateUser)).Methods("PUT", "OPTIONS") router.HandleFunc("/users/{userId}", permissionsManager.WithPermission(modules.Users, operations.Delete, userHandler.deleteUser)).Methods("DELETE", "OPTIONS") @@ -399,3 +399,19 @@ func (h *handler) changePassword(w http.ResponseWriter, r *http.Request, userAut util.WriteJSONObject(r.Context(), w, util.EmptyObject{}) } + +func (h *handler) getOwnUser(w http.ResponseWriter, r *http.Request, userAuth *auth.UserAuth, err error) bool { + s, ok := status.FromError(err) + if !ok || s.ErrorType != status.PermissionDenied { + return false + } + + user, userErr := h.accountManager.GetCurrentUserInfo(r.Context(), *userAuth) + if userErr != nil { + util.WriteError(r.Context(), userErr, w) + return true + } + + util.WriteJSONObject(r.Context(), w, []*api.User{toUserResponse(user.UserInfo, userAuth.UserId)}) + return true +} diff --git a/management/server/peer.go b/management/server/peer.go index 18d49cfe9..69732bd1a 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -33,7 +33,7 @@ const remoteJobsMinVer = "0.64.0" // GetPeers returns a list of peers under the given account filtering out peers that do not belong to a user if // the current user is not an admin. -func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error) { +func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string, all bool) ([]*nbpeer.Peer, error) { user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, userID) if err != nil { return nil, err @@ -44,6 +44,10 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID return nil, err } + if all { + return accountPeers, nil + } + settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthNone, accountID) if err != nil { return nil, fmt.Errorf("failed to get account settings: %w", err)