forked from baron/baron-sso
adminfront: 권한부여 세부 탭에 네이버웍스 연동 권한(worksmobile_viewers/managers) 지원을 추가하고, 세부 권한 부여 자격을 Super Admin 전용으로 승격 (#1183)
This commit is contained in:
@@ -61,7 +61,7 @@ const users = [
|
|||||||
id: "user-owner",
|
id: "user-owner",
|
||||||
name: "Owner User",
|
name: "Owner User",
|
||||||
email: "owner@example.com",
|
email: "owner@example.com",
|
||||||
role: "tenant_admin",
|
role: "super_admin",
|
||||||
status: "active",
|
status: "active",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ import {
|
|||||||
import { toast } from "../../../components/ui/use-toast";
|
import { toast } from "../../../components/ui/use-toast";
|
||||||
import {
|
import {
|
||||||
addTenantRelation,
|
addTenantRelation,
|
||||||
|
fetchMe,
|
||||||
fetchTenantRelations,
|
fetchTenantRelations,
|
||||||
fetchUsers,
|
fetchUsers,
|
||||||
removeTenantRelation,
|
removeTenantRelation,
|
||||||
type TenantRelation,
|
type TenantRelation,
|
||||||
} from "../../../lib/adminApi";
|
} from "../../../lib/adminApi";
|
||||||
import { t } from "../../../lib/i18n";
|
import { t } from "../../../lib/i18n";
|
||||||
import { useTenantPermission } from "../hooks/useTenantPermission";
|
|
||||||
|
|
||||||
interface TenantFineGrainedPermissionsTabProps {
|
interface TenantFineGrainedPermissionsTabProps {
|
||||||
tenantIdProp?: string;
|
tenantIdProp?: string;
|
||||||
@@ -48,8 +48,11 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
}: TenantFineGrainedPermissionsTabProps = {}) {
|
}: TenantFineGrainedPermissionsTabProps = {}) {
|
||||||
const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>();
|
const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>();
|
||||||
const tenantId = tenantIdProp || tenantIdParam || "";
|
const tenantId = tenantIdProp || tenantIdParam || "";
|
||||||
const { hasPermission } = useTenantPermission(tenantId);
|
const { data: profile } = useQuery({
|
||||||
const isWritable = hasPermission("manage_admins");
|
queryKey: ["me"],
|
||||||
|
queryFn: fetchMe,
|
||||||
|
});
|
||||||
|
const isWritable = profile?.role === "super_admin";
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
@@ -75,7 +78,13 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
> = {};
|
> = {};
|
||||||
for (const user of relationsQuery.data) {
|
for (const user of relationsQuery.data) {
|
||||||
initialMap[user.userId] = {};
|
initialMap[user.userId] = {};
|
||||||
const tabs = ["profile", "permissions", "organization", "schema"];
|
const tabs = [
|
||||||
|
"profile",
|
||||||
|
"permissions",
|
||||||
|
"organization",
|
||||||
|
"schema",
|
||||||
|
"worksmobile",
|
||||||
|
];
|
||||||
for (const tab of tabs) {
|
for (const tab of tabs) {
|
||||||
const isWrite = user.relations.includes(`${tab}_managers`);
|
const isWrite = user.relations.includes(`${tab}_managers`);
|
||||||
const isRead = user.relations.includes(`${tab}_viewers`);
|
const isRead = user.relations.includes(`${tab}_viewers`);
|
||||||
@@ -337,6 +346,12 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
<TableHead className="font-bold">
|
<TableHead className="font-bold">
|
||||||
{t("ui.admin.tenants.detail.tab_schema", "사용자 스키마")}
|
{t("ui.admin.tenants.detail.tab_schema", "사용자 스키마")}
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
<TableHead className="font-bold">
|
||||||
|
{t(
|
||||||
|
"ui.admin.tenants.detail.tab_worksmobile",
|
||||||
|
"네이버웍스 연동",
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
<TableHead className="font-bold text-center w-20">
|
<TableHead className="font-bold text-center w-20">
|
||||||
{t("ui.common.action", "작업")}
|
{t("ui.common.action", "작업")}
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@@ -346,7 +361,7 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
{relations.length === 0 ? (
|
{relations.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell
|
<TableCell
|
||||||
colSpan={6}
|
colSpan={7}
|
||||||
className="text-center py-12 text-muted-foreground"
|
className="text-center py-12 text-muted-foreground"
|
||||||
>
|
>
|
||||||
{t(
|
{t(
|
||||||
@@ -387,6 +402,14 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
? "read"
|
? "read"
|
||||||
: "none";
|
: "none";
|
||||||
|
|
||||||
|
const worksmobileVal = user.relations.includes(
|
||||||
|
"worksmobile_managers",
|
||||||
|
)
|
||||||
|
? "write"
|
||||||
|
: user.relations.includes("worksmobile_viewers")
|
||||||
|
? "read"
|
||||||
|
: "none";
|
||||||
|
|
||||||
const curProfileVal =
|
const curProfileVal =
|
||||||
localTenantPermissions[user.userId]?.profile ??
|
localTenantPermissions[user.userId]?.profile ??
|
||||||
profileVal;
|
profileVal;
|
||||||
@@ -398,6 +421,9 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
organizationVal;
|
organizationVal;
|
||||||
const curSchemaVal =
|
const curSchemaVal =
|
||||||
localTenantPermissions[user.userId]?.schema ?? schemaVal;
|
localTenantPermissions[user.userId]?.schema ?? schemaVal;
|
||||||
|
const curWorksmobileVal =
|
||||||
|
localTenantPermissions[user.userId]?.worksmobile ??
|
||||||
|
worksmobileVal;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
@@ -562,6 +588,43 @@ export function TenantFineGrainedPermissionsTab({
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<select
|
||||||
|
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
value={curWorksmobileVal}
|
||||||
|
disabled={!isWritable}
|
||||||
|
name={`tenant-fine-grained-worksmobile-${user.userId}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
const nextVal = e.target.value as
|
||||||
|
| "none"
|
||||||
|
| "read"
|
||||||
|
| "write";
|
||||||
|
setLocalTenantPermissions((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[user.userId]: {
|
||||||
|
...(prev[user.userId] ?? {}),
|
||||||
|
worksmobile: nextVal,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
handleRelationChange(
|
||||||
|
user.userId,
|
||||||
|
"worksmobile",
|
||||||
|
worksmobileVal,
|
||||||
|
nextVal,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="none">
|
||||||
|
{t("ui.common.none", "권한 없음")}
|
||||||
|
</option>
|
||||||
|
<option value="read">
|
||||||
|
{t("ui.common.read", "조회 가능 (Read)")}
|
||||||
|
</option>
|
||||||
|
<option value="write">
|
||||||
|
{t("ui.common.write", "수정 가능 (Write)")}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</TableCell>
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
Reference in New Issue
Block a user