mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
feat(hooks): permission-driven gating via useHasPermission
Replace the rank-level family (useHasRankLevel + STAFF_LEVELS constants + useIsRank) with a permission-driven family that reads straight from the deployment's `permission_definitions` table — no more hardcoded SecurityLevel/rank-id thresholds on the client. A new rank in permission_ranks or a re-shuffling of permission_definitions rank columns now propagates through the UI automatically. Renderer-side wire shipped in companion commit feat/react19-event-bus@159c5eb (UserPermissionsMapParser + Event, SessionDataManager.getPermissionsSnapshot + USER_PERMISSIONS_UPDATED). New public API in `useSessionSnapshots.ts`: - useUserPermissions(): ReadonlyMap<string, number> — full map - useHasPermission(key): boolean — > 0 ⇒ true - usePermissionValue(key): number — raw 1/2 or 0 - useIsAmbassador() now aliases useHasPermission('acc_ambassador') - useUserRank() kept for PRESENTATIONAL use only (badge, prefix, prefix color) — documented as such in JSDoc; gating must use useHasPermission. Dropped: - src/api/nitro/session/RankLevels.ts (STAFF_LEVELS constants) - useHasRankLevel / useIsRank exports (rank-based gating) 11 consumer migrations, each mapped to the right `permission_definitions.permission_key`: - ToolbarView (mod-only chat-input button) → acc_supporttool - ChooserWidgetView (room-object id column) → acc_supporttool - CatalogClassicView (admin toggles) → acc_catalogfurni - CatalogModernView (admin toggles) → acc_catalogfurni - FurniEditorView (panel access) → acc_catalogfurni - CalendarView (force-open day) → acc_calendar_force - InfoStandWidgetFurniView (mod buildtools btn) → acc_anyroomowner - AvatarInfoWidgetPetView (canPickUp) → acc_anyroomowner - FurnitureMannequinView (controller mode) → acc_anyroomowner - YouTubePlayerView (isMyRoom) → acc_anyroomowner - NavigatorRoomInfoView 'settings' → acc_anyroomowner - NavigatorRoomInfoView 'staff_pick' → acc_staff_pick Test refresh: - useUserRank still tested for the presentational shape. - useHasPermission: true for non-zero, false for absent/zero. - usePermissionValue: raw 1 / 2 / 0 (default). - useUserPermissions: full map exposure. - Runtime promote test: mutate the permissions map + dispatch USER_PERMISSIONS_UPDATED, assert useHasPermission flips false→true. Locks in the new reactive contract. Mock unchanged (the test sets getPermissionsSnapshot via vi.mocked). Verification: yarn typecheck clean, yarn lint:hooks clean, yarn test 214/214 (213 prior + 1 net new for useUserPermissions). Backward compatible: older Arcturus deployments don't ship the map → empty snapshot → every gate is false → mod UI hidden (safe default).
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { CreateLinkEvent, GetCustomRoomFilterMessageComposer, GetGuestRoomMessageComposer, GetSessionDataManager, NavigatorSearchComposer, RemoveOwnRoomRightsRoomMessageComposer, RoomControllerLevel, RoomMuteComposer, RoomSettingsComposer, ToggleStaffPickMessageComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { FaLink, FaSignOutAlt } from 'react-icons/fa';
|
||||
import { DispatchUiEvent, GetGroupInformation, LocalizeText, ReportType, SendMessageComposer, STAFF_LEVELS, ToggleFavoriteRoom } from '../../../api';
|
||||
import { DispatchUiEvent, GetGroupInformation, LocalizeText, ReportType, SendMessageComposer, ToggleFavoriteRoom } from '../../../api';
|
||||
import { Button, Column, Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text, UserProfileIconView } from '../../../common';
|
||||
import { RoomWidgetThumbnailEvent } from '../../../events';
|
||||
import { useHasRankLevel, useHelp, useNavigator, useRoom } from '../../../hooks';
|
||||
import { useHasPermission, useHelp, useNavigator, useRoom } from '../../../hooks';
|
||||
import { classNames } from '../../../layout';
|
||||
|
||||
export interface NavigatorRoomInfoViewProps {
|
||||
@@ -19,8 +19,8 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
|
||||
const { report = null } = useHelp();
|
||||
const { navigatorData = null, favouriteRoomIds = [] } = useNavigator();
|
||||
const { roomSession = null } = useRoom();
|
||||
const isModerator = useHasRankLevel(STAFF_LEVELS.MOD);
|
||||
const isAdmin = useHasRankLevel(STAFF_LEVELS.ADMIN);
|
||||
const canManageAnyRoom = useHasPermission('acc_anyroomowner');
|
||||
const canStaffPick = useHasPermission('acc_staff_pick');
|
||||
|
||||
const enteredRoomId = navigatorData?.enteredGuestRoom?.roomId ?? 0;
|
||||
|
||||
@@ -53,9 +53,9 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
|
||||
switch(permission)
|
||||
{
|
||||
case 'settings':
|
||||
return (GetSessionDataManager().userId === navigatorData.enteredGuestRoom.ownerId || isModerator);
|
||||
return (GetSessionDataManager().userId === navigatorData.enteredGuestRoom.ownerId || canManageAnyRoom);
|
||||
case 'staff_pick':
|
||||
return isAdmin;
|
||||
return canStaffPick;
|
||||
case 'floor':
|
||||
return roomSession?.controllerLevel >= RoomControllerLevel.GUEST;
|
||||
case 'guest':
|
||||
|
||||
Reference in New Issue
Block a user