1
0
forked from baron/baron-sso

chore: fix formatting and lint errors across Makefile, backend, and adminfront

This commit addresses several linting and formatting issues that caused CI checks to fail:
- Makefile: Removed obsolete '--organize-imports-enabled' from Biome and switched to '@biomejs/biome'.
- backend: Fixed spacing and alignment issues according to gofmt.
- adminfront: Fixed multiple unused variables and imports, and configured unsafe fixes in the Biome config to remove dead code.
This commit is contained in:
2026-05-29 15:31:30 +09:00
parent b33aabbb68
commit 2da470922b
27 changed files with 124 additions and 147 deletions

View File

@@ -3,7 +3,6 @@ import type { AxiosError } from "axios";
import { Download, NotebookTabs, RefreshCw, Search } from "lucide-react";
import * as React from "react";
import {
formatAuditValue,
parseAuditDetails,
resolveAuditAction,
resolveAuditActor,

View File

@@ -23,7 +23,6 @@ import {
fetchDataIntegrityReport,
type RPUsageDailyMetric,
type RPUsagePeriod,
type TenantSummary,
} from "../../lib/adminApi";
import { t } from "../../lib/i18n";

View File

@@ -5,7 +5,6 @@ import {
Plus,
Search,
ShieldCheck,
Trash2,
UserPlus,
Users,
} from "lucide-react";
@@ -28,7 +27,6 @@ import {
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import {
@@ -68,7 +66,7 @@ function mergePendingMembers(
export function TenantAdminsAndOwnersTab() {
const auth = useAuth();
const navigate = useNavigate();
const currentUserId = auth.user?.profile.sub;
const _currentUserId = auth.user?.profile.sub;
const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>();
const tenantId = tenantIdParam ?? "";
const queryClient = useQueryClient();
@@ -187,7 +185,7 @@ export function TenantAdminsAndOwnersTab() {
),
);
},
onError: (err: AxiosError<{ error?: string }>, userId, context) => {
onError: (err: AxiosError<{ error?: string }>, _userId, context) => {
if (context?.previousOwners) {
queryClient.setQueryData(
["tenant-owners", tenantId],
@@ -288,7 +286,7 @@ export function TenantAdminsAndOwnersTab() {
t("msg.admin.tenants.admins.remove_success", "권한이 회수되었습니다."),
);
},
onError: (err: AxiosError<{ error?: string }>, userId, context) => {
onError: (err: AxiosError<{ error?: string }>, _userId, context) => {
if (context?.previousAdmins) {
queryClient.setQueryData(
["tenant-admins", tenantId],
@@ -310,7 +308,7 @@ export function TenantAdminsAndOwnersTab() {
}
};
const handleRemoveOwner = (userId: string, userName: string) => {
const _handleRemoveOwner = (userId: string, userName: string) => {
if (
window.confirm(
t(
@@ -324,7 +322,7 @@ export function TenantAdminsAndOwnersTab() {
}
};
const handleRemoveAdmin = (userId: string, userName: string) => {
const _handleRemoveAdmin = (userId: string, userName: string) => {
if (
window.confirm(
t(

View File

@@ -1,7 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { Copy } from "lucide-react";
import { Link, Outlet, useLocation, useParams } from "react-router-dom";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
import { fetchMe, fetchTenant } from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";

View File

@@ -38,7 +38,6 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import { Label } from "../../../components/ui/label";
@@ -239,7 +238,7 @@ const UserGroupTreeNode: React.FC<UserGroupTreeNodeProps> = ({
function TenantGroupsPage() {
const params = useParams<{ tenantId: string }>();
const tenantId = params.tenantId ?? "";
const queryClient = useQueryClient();
const _queryClient = useQueryClient();
const [newGroupName, setNewGroupName] = useState("");
const [newGroupDesc, setNewGroupNameDesc] = useState("");

View File

@@ -4,7 +4,6 @@ import {
useMutation,
useQuery,
} from "@tanstack/react-query";
import { useVirtualizer } from "@tanstack/react-virtual";
import type { AxiosError } from "axios";
import {
ArrowDown,
@@ -14,7 +13,6 @@ import {
ChevronDown,
ChevronRight,
Download,
ExternalLink,
FileSpreadsheet,
LayoutDashboard,
List,
@@ -28,22 +26,13 @@ import {
import * as React from "react";
import { Link, useNavigate } from "react-router-dom";
import { PageHeader } from "../../../../../common/core/components/page";
import {
SortableTableHead,
sortableTableHeadBaseClassName,
sortableTableHeaderClassName,
} from "../../../../../common/core/components/sort";
import {
type SortConfig,
type SortResolverMap,
sortItems,
toggleSort,
} from "../../../../../common/core/utils";
import {
commonStickyTableHeaderClass,
commonTableShellClass,
commonTableViewportClass,
} from "../../../../../common/ui/table";
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
import { RoleGuard } from "../../../components/auth/RoleGuard";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
@@ -71,7 +60,6 @@ import {
DropdownMenuTrigger,
} from "../../../components/ui/dropdown-menu";
import { Input } from "../../../components/ui/input";
import { ScrollArea } from "../../../components/ui/scroll-area";
import {
Select,
SelectContent,
@@ -79,7 +67,6 @@ import {
SelectTrigger,
SelectValue,
} from "../../../components/ui/select";
import { Separator } from "../../../components/ui/separator";
import { Switch } from "../../../components/ui/switch";
import {
Table,
@@ -132,13 +119,12 @@ import {
const tenantCSVTemplate =
"name,type,parent_tenant_slug,slug,memo,email_domain,visibility,org_unit_type\n";
const tenantPageSize = 500;
const tenantVirtualizationThreshold = 250;
const tenantEstimatedRowHeight = 73;
const tenantLoadAheadPx = 360;
const tenantLoadAheadRows = 30;
const _tenantVirtualizationThreshold = 250;
const _tenantEstimatedRowHeight = 73;
const _tenantLoadAheadPx = 360;
const _tenantLoadAheadRows = 30;
type TenantSortKey = keyof TenantSummary | "recursiveMemberCount";
type TenantListRow = TenantSummary & { recursiveMemberCount: number };
const getTenantIcon = (type?: string) => {
switch (type?.toUpperCase()) {
@@ -301,7 +287,7 @@ function TenantListPage() {
>({});
const [previewOpen, setPreviewOpen] = React.useState(false);
const [selectedBulkStatus, setSelectedBulkStatus] = React.useState("");
const tenantTableScrollRef = React.useRef<HTMLDivElement | null>(null);
const _tenantTableScrollRef = React.useRef<HTMLDivElement | null>(null);
const { data: profile } = useQuery({
queryKey: ["me"],
@@ -1368,8 +1354,8 @@ const TenantHierarchyView: React.FC<{
selectedIds,
onSelect,
onSelectAll,
onDelete,
isDeletePending,
onDelete: _onDelete,
isDeletePending: _isDeletePending,
search,
deletableTenants,
statusMutation,

View File

@@ -1,5 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { ArrowRight, Building2, Plus } from "lucide-react";
import { Building2, Plus } from "lucide-react";
import { Link, useNavigate, useParams } from "react-router-dom";
import {
commonStickyTableHeaderClass,

View File

@@ -1,14 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
Loader2,
Mail,
MoreHorizontal,
Plus,
User,
UserMinus,
UserPlus,
} from "lucide-react";
import { Loader2, Mail, Plus, User, UserPlus } from "lucide-react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
import { Badge } from "../../../components/ui/badge";
@@ -19,12 +11,6 @@ import {
CardHeader,
CardTitle,
} from "../../../components/ui/card";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "../../../components/ui/dropdown-menu";
import {
Table,
TableBody,
@@ -80,7 +66,7 @@ function TenantUsersPage() {
},
});
const handleRemoveMember = (userId: string, userName: string) => {
const _handleRemoveMember = (userId: string, userName: string) => {
if (!tenantSlug) return;
if (
window.confirm(

View File

@@ -1,6 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { Building2, Plus, Users } from "lucide-react";
import { useState } from "react";
import { Link } from "react-router-dom";
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
import { Badge } from "../../../components/ui/badge";

View File

@@ -6,7 +6,6 @@ import {
Building2,
ChevronDown,
ChevronRight,
CornerDownRight,
Download,
ExternalLink,
FolderOpen,
@@ -41,7 +40,6 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import {
DropdownMenu,
@@ -52,7 +50,6 @@ import {
DropdownMenuTrigger,
} from "../../../components/ui/dropdown-menu";
import { Input } from "../../../components/ui/input";
import { Label } from "../../../components/ui/label";
import { ScrollArea } from "../../../components/ui/scroll-area";
import {
Table,
@@ -62,15 +59,8 @@ import {
TableHeader,
TableRow,
} from "../../../components/ui/table";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "../../../components/ui/tabs";
import { toast } from "../../../components/ui/use-toast";
import {
createUser,
exportTenantsCSV,
fetchAllTenants,
fetchUsers,
@@ -413,7 +403,7 @@ const MemberTable: React.FC<{
function TenantUserGroupsTab() {
const { tenantId } = useParams<{ tenantId: string }>();
const navigate = useNavigate();
const _navigate = useNavigate();
const queryClient = useQueryClient();
const [selectedNodeId, setSelectedNodeId] = useState<string>(tenantId || "");
@@ -452,7 +442,7 @@ function TenantUserGroupsTab() {
queryFn: () => fetchAllTenants(),
});
const { currentBase, subTree } = useMemo(() => {
const { currentBase, subTree: _subTree } = useMemo(() => {
const allItems = allTenantsData?.items ?? [];
return buildTenantFullTree(allItems, tenantId);
}, [allTenantsData, tenantId]);
@@ -855,7 +845,7 @@ const UserAddDialog: React.FC<{
try {
const res = await fetchUsers(20, 0, userSearch);
setSearchResults(res.items);
} catch (err) {
} catch (_err) {
toast.error(t("msg.admin.users.list.fetch_error", "사용자 검색 실패"));
} finally {
setIsSearching(false);

View File

@@ -8,7 +8,6 @@ import {
Plus,
Save,
Trash2,
Mail,
X,
} from "lucide-react";
import * as React from "react";
@@ -22,7 +21,6 @@ import {
CardHeader,
CardTitle,
} from "../../components/ui/card";
import { Checkbox } from "../../components/ui/checkbox";
import {
Dialog,
DialogContent,
@@ -184,7 +182,7 @@ function UserCreatePage() {
if (e.key === "Enter" || e.key === "," || e.key === " ") {
e.preventDefault();
const value = newSubEmail.trim().replace(/,/g, "");
if (value && value.includes("@") && !currentSubEmails.includes(value)) {
if (value?.includes("@") && !currentSubEmails.includes(value)) {
setValue("metadata.sub_email", [...currentSubEmails, value], {
shouldDirty: true,
});
@@ -667,8 +665,7 @@ function UserCreatePage() {
onClick={() => {
const value = newSubEmail.trim().replace(/,/g, "");
if (
value &&
value.includes("@") &&
value?.includes("@") &&
!currentSubEmails.includes(value)
) {
setValue(

View File

@@ -35,7 +35,6 @@ import {
CardHeader,
CardTitle,
} from "../../components/ui/card";
import { Checkbox } from "../../components/ui/checkbox";
import {
Dialog,
DialogContent,
@@ -322,8 +321,8 @@ function UserDetailPage() {
const userId = params.id ?? "";
const navigate = useNavigate();
const queryClient = useQueryClient();
const [error, setError] = React.useState<string | null>(null);
const [successMsg, setSuccessMsg] = React.useState<string | null>(null);
const [_error, _setError] = React.useState<string | null>(null);
const [_successMsg, _setSuccessMsg] = React.useState<string | null>(null);
const [isPasswordResetOpen, setIsPasswordResetOpen] = React.useState(false);
const [generatedPassword, setGeneratedPassword] = React.useState<
string | null
@@ -419,7 +418,7 @@ function UserDetailPage() {
if (e.key === "Enter" || e.key === "," || e.key === " ") {
e.preventDefault();
const value = newSubEmail.trim().replace(/,/g, "");
if (value && value.includes("@") && !currentSubEmails.includes(value)) {
if (value?.includes("@") && !currentSubEmails.includes(value)) {
setValue("metadata.sub_email", [...currentSubEmails, value], {
shouldDirty: true,
});
@@ -595,7 +594,7 @@ function UserDetailPage() {
);
};
const setPrimaryAppointment = (targetIndex: number) => {
const _setPrimaryAppointment = (targetIndex: number) => {
setAdditionalAppointments((current) =>
current.map((appointment, index) => ({
...appointment,
@@ -662,14 +661,14 @@ function UserDetailPage() {
string,
Record<string, string | number | boolean>
>) || {}),
sub_email: Array.isArray(user.metadata?.sub_email)
sub_email: (Array.isArray(user.metadata?.sub_email)
? user.metadata.sub_email
: typeof user.metadata?.sub_email === "string"
? user.metadata.sub_email
.split(/[;,\n\r\t]/)
.map((e) => e.trim())
.filter((e) => e.includes("@"))
: [],
: []) as unknown[],
},
});
const isUserHanmacFamily = isHanmacFamilyUser(
@@ -792,14 +791,17 @@ function UserDetailPage() {
sub_email: rawSubEmail,
...safeMetadata
} = cleanMetadata;
// Parse sub_email
let sub_email: string[] = [];
if (typeof rawSubEmail === "string" && rawSubEmail.trim() !== "") {
sub_email = rawSubEmail
if (
typeof rawSubEmail === "string" &&
(rawSubEmail as string).trim() !== ""
) {
sub_email = (rawSubEmail as string)
.split(/[;,\n\r\t]/)
.map((e) => e.trim())
.filter((e) => e.includes("@"));
.map((e: string) => e.trim())
.filter((e: string) => e.includes("@"));
}
const metadata: Record<string, unknown> = {
@@ -813,7 +815,7 @@ function UserDetailPage() {
};
// email cannot be updated directly via this API in current backend implementation,
// so we delete it from payload if it spread
// @ts-ignore
// @ts-expect-error
delete payload.email;
payload.role = undefined;
@@ -989,13 +991,13 @@ function UserDetailPage() {
<Mail size={14} className="text-primary/70" />
{user.email}
</div>
{user.metadata?.sub_email &&
{!!user.metadata?.sub_email &&
Array.isArray(user.metadata.sub_email) &&
user.metadata.sub_email.length > 0 && (
(user.metadata.sub_email as unknown[]).length > 0 && (
<div className="flex items-center gap-1.5 bg-background px-2.5 py-1 rounded-full border">
<Mail size={14} className="text-primary/40" />
<span className="text-[10px] font-bold">
+{user.metadata.sub_email.length}
+{(user.metadata.sub_email as unknown[]).length}
</span>
</div>
)}
@@ -1167,8 +1169,7 @@ function UserDetailPage() {
onClick={() => {
const value = newSubEmail.trim().replace(/,/g, "");
if (
value &&
value.includes("@") &&
value?.includes("@") &&
!currentSubEmails.includes(value)
) {
setValue(

View File

@@ -1,5 +1,5 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createI18nMock } from "../../test/i18nMock";

View File

@@ -13,7 +13,6 @@ import {
ChevronDown,
ChevronLeft,
ChevronRight,
Download,
FileDown,
FileSpreadsheet,
LayoutDashboard,
@@ -268,7 +267,7 @@ const UserListSearchControls = React.memo(function UserListSearchControls({
});
function UserListPage() {
const navigate = useNavigate();
const _navigate = useNavigate();
const [page, setPage] = React.useState(1);
const [search, setSearch] = React.useState("");
const [selectedCompany, setSelectedCompany] = React.useState<string>("");
@@ -563,7 +562,7 @@ function UserListPage() {
},
});
const handleApplyBulkStatus = () => {
const _handleApplyBulkStatus = () => {
if (selectedUserIds.length === 0 || !selectedBulkStatus) return;
bulkUpdateMutation.mutate({
userIds: selectedUserIds,
@@ -571,7 +570,7 @@ function UserListPage() {
});
};
const handleApplyBulkPermission = () => {
const _handleApplyBulkPermission = () => {
if (selectedUserIds.length === 0 || !selectedBulkPermission) return;
bulkUpdateMutation.mutate({
userIds: selectedUserIds,
@@ -594,7 +593,7 @@ function UserListPage() {
}
};
const handleDelete = (userId: string, userName: string) => {
const _handleDelete = (userId: string, userName: string) => {
if (
!window.confirm(
t(

View File

@@ -19,8 +19,6 @@ import {
bulkUpdateUsers,
fetchAllTenants,
fetchGroups,
type GroupSummary,
type TenantSummary,
type UserSummary,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";
@@ -49,7 +47,7 @@ export function UserBulkMoveGroupModal({
const [searchTerm, setSearchTerm] = React.useState("");
const [acknowledgeWarning, setAcknowledgeWarning] = React.useState(false);
const queryClient = useQueryClient();
const _queryClient = useQueryClient();
const { data: tenantsData } = useQuery({
queryKey: ["tenants", "all"],

View File

@@ -102,7 +102,7 @@ export function isHanmacFamilyTenant<T extends TenantFilterTarget>(
tenants: T[],
hanmacFamilyTenantId?: string,
) {
if (!tenant || !tenant.id) return false;
if (!tenant?.id) return false;
const rootTenantId = resolveHanmacFamilyTenantId(
tenants,

View File

@@ -141,8 +141,7 @@ primary@samaneng.com,Primary User,rnd-saman,EMP001,secondary@hanmaceng.co.kr`;
tenantSlug: "rnd-saman",
metadata: {
employee_id: "EMP001",
sub_email: "secondary@hanmaceng.co.kr",
secondary_emails: ["secondary@hanmaceng.co.kr"],
sub_email: ["secondary@hanmaceng.co.kr"],
aliasEmails: ["secondary@hanmaceng.co.kr"],
},
});