Implement SUPER_ADMIN permission checks in user management
- Added validation to ensure that only existing SUPER_ADMIN users can grant or modify SUPER_ADMIN permissions. - Updated the user management page to reflect that both SUPER_ADMIN and COMPANY_ADMIN can access the user permissions, while COMPANY_ADMIN cannot grant SUPER_ADMIN rights. - Enhanced the user authorization modal to prevent COMPANY_ADMIN from changing SUPER_ADMIN permissions, ensuring proper access control. These changes improve the security and integrity of user role management within the application.
This commit is contained in:
@@ -20,14 +20,16 @@ interface UserAuthEditModalProps {
|
||||
onClose: () => void;
|
||||
onSuccess?: () => void;
|
||||
user: any | null;
|
||||
currentUser?: any | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 권한 변경 모달
|
||||
*
|
||||
* 권한 레벨만 변경 가능 (최고 관리자 전용)
|
||||
* 권한 레벨만 변경 가능 (관리자 전용)
|
||||
* 회사관리자는 SUPER_ADMIN 권한 부여 불가
|
||||
*/
|
||||
export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuthEditModalProps) {
|
||||
export function UserAuthEditModal({ isOpen, onClose, onSuccess, user, currentUser }: UserAuthEditModalProps) {
|
||||
const [selectedUserType, setSelectedUserType] = useState<string>("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||
@@ -79,7 +81,19 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth
|
||||
},
|
||||
];
|
||||
|
||||
const selectedOption = userTypeOptions.find((opt) => opt.value === selectedUserType);
|
||||
// 현재 사용자가 SUPER_ADMIN인지 확인
|
||||
const isCurrentUserSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN";
|
||||
|
||||
// COMPANY_ADMIN은 SUPER_ADMIN 옵션 제외
|
||||
const availableOptions = isCurrentUserSuperAdmin
|
||||
? userTypeOptions
|
||||
: userTypeOptions.filter((opt) => opt.value !== "SUPER_ADMIN");
|
||||
|
||||
// 대상 사용자가 SUPER_ADMIN이면 COMPANY_ADMIN은 변경 불가
|
||||
const isTargetSuperAdmin = user?.userType === "SUPER_ADMIN";
|
||||
const canEdit = isCurrentUserSuperAdmin || !isTargetSuperAdmin;
|
||||
|
||||
const selectedOption = availableOptions.find((opt) => opt.value === selectedUserType);
|
||||
|
||||
// 권한 변경 여부 확인
|
||||
const isUserTypeChanged = user && selectedUserType !== user.userType;
|
||||
@@ -160,22 +174,32 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth
|
||||
<Label htmlFor="userType" className="text-sm font-medium">
|
||||
새로운 권한 <span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<Select value={selectedUserType} onValueChange={setSelectedUserType}>
|
||||
<SelectTrigger className="h-10">
|
||||
<SelectValue placeholder="권한 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{userTypeOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={option.color}>{option.icon}</span>
|
||||
<span>{option.label}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{selectedOption && <p className="text-muted-foreground text-xs">{selectedOption.description}</p>}
|
||||
{!canEdit ? (
|
||||
<div className="rounded-lg border border-orange-300 bg-amber-50 p-3">
|
||||
<p className="text-xs text-orange-800">
|
||||
최고 관리자의 권한은 다른 최고 관리자만 변경할 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Select value={selectedUserType} onValueChange={setSelectedUserType}>
|
||||
<SelectTrigger className="h-10">
|
||||
<SelectValue placeholder="권한 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{availableOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={option.color}>{option.icon}</span>
|
||||
<span>{option.label}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{selectedOption && <p className="text-muted-foreground text-xs">{selectedOption.description}</p>}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* SUPER_ADMIN 경고 */}
|
||||
@@ -206,7 +230,7 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={isLoading || !isUserTypeChanged}
|
||||
disabled={isLoading || !isUserTypeChanged || !canEdit}
|
||||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
{isLoading ? "처리중..." : showConfirmation ? "확인 및 저장" : "저장"}
|
||||
|
||||
Reference in New Issue
Block a user