mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-03 05:13:09 +00:00
160 lines
4.7 KiB
TypeScript
160 lines
4.7 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { useAuth } from './useAuth';
|
|
import { useForumData } from './useForumData';
|
|
import { EVerificationStatus } from '@opchan/core';
|
|
|
|
export interface Permission {
|
|
canPost: boolean;
|
|
canComment: boolean;
|
|
canVote: boolean;
|
|
canCreateCell: boolean;
|
|
canModerate: (cellId: string) => boolean;
|
|
canDelegate: boolean;
|
|
canUpdateProfile: boolean;
|
|
}
|
|
|
|
export interface PermissionReasons {
|
|
voteReason: string;
|
|
postReason: string;
|
|
commentReason: string;
|
|
createCellReason: string;
|
|
moderateReason: (cellId: string) => string;
|
|
}
|
|
|
|
export interface PermissionResult {
|
|
allowed: boolean;
|
|
reason: string;
|
|
}
|
|
|
|
/**
|
|
* Unified permission system with single source of truth for all permission logic
|
|
*/
|
|
export function usePermissions(): Permission &
|
|
PermissionReasons & {
|
|
checkPermission: (
|
|
action: keyof Permission,
|
|
cellId?: string
|
|
) => PermissionResult;
|
|
} {
|
|
const { currentUser, verificationStatus } = useAuth();
|
|
const { cellsWithStats } = useForumData();
|
|
|
|
// Single source of truth for all permission logic
|
|
const permissions = useMemo((): Permission => {
|
|
const isWalletConnected =
|
|
verificationStatus === EVerificationStatus.WALLET_CONNECTED;
|
|
const isVerified =
|
|
verificationStatus === EVerificationStatus.ENS_ORDINAL_VERIFIED;
|
|
|
|
return {
|
|
canPost: isWalletConnected || isVerified,
|
|
canComment: isWalletConnected || isVerified,
|
|
canVote: isWalletConnected || isVerified,
|
|
canCreateCell: isVerified, // Only ENS/Ordinal owners
|
|
canModerate: (cellId: string) => {
|
|
if (!currentUser || !cellId) return false;
|
|
// Check if user is the creator of the cell
|
|
const cell = cellsWithStats.find(c => c.id === cellId);
|
|
return cell ? cell.author === currentUser.address : false;
|
|
},
|
|
canDelegate: isWalletConnected || isVerified,
|
|
canUpdateProfile: Boolean(currentUser),
|
|
};
|
|
}, [currentUser, verificationStatus, cellsWithStats]);
|
|
|
|
// Single source of truth for permission reasons
|
|
const reasons = useMemo((): PermissionReasons => {
|
|
if (!currentUser) {
|
|
return {
|
|
voteReason: 'Connect your wallet to vote',
|
|
postReason: 'Connect your wallet to post',
|
|
commentReason: 'Connect your wallet to comment',
|
|
createCellReason: 'Connect your wallet to create cells',
|
|
moderateReason: () => 'Connect your wallet to moderate',
|
|
};
|
|
}
|
|
|
|
return {
|
|
voteReason: permissions.canVote
|
|
? 'You can vote'
|
|
: 'Connect your wallet to vote',
|
|
postReason: permissions.canPost
|
|
? 'You can post'
|
|
: 'Connect your wallet to post',
|
|
commentReason: permissions.canComment
|
|
? 'You can comment'
|
|
: 'Connect your wallet to comment',
|
|
createCellReason: permissions.canCreateCell
|
|
? 'You can create cells'
|
|
: 'Verify ENS or Logos ordinal to create cells',
|
|
moderateReason: (cellId: string) => {
|
|
if (!cellId) return 'Cell ID required';
|
|
return permissions.canModerate(cellId)
|
|
? 'You can moderate this cell'
|
|
: 'Only cell creators can moderate';
|
|
},
|
|
};
|
|
}, [currentUser, verificationStatus, permissions]);
|
|
|
|
// Unified permission checker
|
|
const checkPermission = useMemo(() => {
|
|
return (action: keyof Permission, cellId?: string): PermissionResult => {
|
|
let allowed = false;
|
|
let reason = '';
|
|
|
|
switch (action) {
|
|
case 'canVote':
|
|
allowed = permissions.canVote;
|
|
reason = reasons.voteReason;
|
|
break;
|
|
|
|
case 'canPost':
|
|
allowed = permissions.canPost;
|
|
reason = reasons.postReason;
|
|
break;
|
|
|
|
case 'canComment':
|
|
allowed = permissions.canComment;
|
|
reason = reasons.commentReason;
|
|
break;
|
|
|
|
case 'canCreateCell':
|
|
allowed = permissions.canCreateCell;
|
|
reason = reasons.createCellReason;
|
|
break;
|
|
|
|
case 'canModerate':
|
|
allowed = cellId ? permissions.canModerate(cellId) : false;
|
|
reason = cellId ? reasons.moderateReason(cellId) : 'Cell ID required';
|
|
break;
|
|
|
|
case 'canDelegate':
|
|
allowed = permissions.canDelegate;
|
|
reason = allowed
|
|
? 'You can delegate keys'
|
|
: 'Connect your wallet to delegate keys';
|
|
break;
|
|
|
|
case 'canUpdateProfile':
|
|
allowed = permissions.canUpdateProfile;
|
|
reason = allowed
|
|
? 'You can update your profile'
|
|
: 'Connect your wallet to update profile';
|
|
break;
|
|
|
|
default:
|
|
allowed = false;
|
|
reason = 'Unknown permission';
|
|
}
|
|
|
|
return { allowed, reason };
|
|
};
|
|
}, [permissions, reasons]);
|
|
|
|
return {
|
|
...permissions,
|
|
...reasons,
|
|
checkPermission,
|
|
};
|
|
}
|