Răsfoiți Sursa

changed to filter by username instead of userid

ryosei-f 1 lună în urmă
părinte
comite
0287f2a926

+ 5 - 3
apps/app/src/client/components/Admin/AuditLog/AuditLogExportModal.tsx

@@ -32,7 +32,7 @@ const AuditLogExportModalSubstance = ({
 
   const [startDate, setStartDate] = useState<Date | null>(null);
   const [endDate, setEndDate] = useState<Date | null>(null);
-  const [_selectedUsernames, setSelectedUsernames] = useState<string[]>([]);
+  const [selectedUsernames, setSelectedUsernames] = useState<string[]>([]);
   const [actionMap, setActionMap] = useState(
     () =>
       new Map<SupportedActionType, boolean>(
@@ -79,8 +79,10 @@ const AuditLogExportModalSubstance = ({
       .map((v) => v[0]);
 
     const filters: IAuditLogBulkExportFilters = {};
-    // TODO: Add users filter after implementing username-to-userId conversion
 
+    if (selectedUsernames.length > 0) {
+      filters.usernames = selectedUsernames;
+    }
     if (selectedActionList.length > 0) {
       filters.actions = selectedActionList;
     }
@@ -92,7 +94,7 @@ const AuditLogExportModalSubstance = ({
     }
 
     return filters;
-  }, [actionMap, startDate, endDate]);
+  }, [actionMap, selectedUsernames, startDate, endDate]);
 
   const {
     isExporting,

+ 1 - 1
apps/app/src/features/audit-log-bulk-export/interfaces/audit-log-bulk-export.ts

@@ -24,7 +24,7 @@ export type AuditLogBulkExportJobStatus =
   (typeof AuditLogBulkExportJobStatus)[keyof typeof AuditLogBulkExportJobStatus];
 
 export interface IAuditLogBulkExportFilters {
-  users?: Array<Ref<IUser>>;
+  usernames?: string[];
   actions?: SupportedActionType[];
   dateFrom?: Date;
   dateTo?: Date;

+ 1 - 1
apps/app/src/features/audit-log-bulk-export/server/models/audit-log-bulk-export-job.ts

@@ -20,7 +20,7 @@ const auditLogBulkExportJobSchema = new Schema<IAuditLogBulkExportJob>(
     user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
     filters: {
       type: {
-        users: [{ type: Schema.Types.ObjectId, ref: 'User' }],
+        usernames: [{ type: String }],
         actions: [{ type: String, enum: AllSupportedActions }],
         dateFrom: { type: Date },
         dateTo: { type: Date },

+ 3 - 3
apps/app/src/features/audit-log-bulk-export/server/routes/apiv3/audit-log-bulk-export.ts

@@ -24,7 +24,7 @@ const router = Router();
 
 interface AuditLogExportReqBody {
   filters: {
-    users?: string[];
+    usernames?: string[];
     actions?: SupportedActionType[];
     dateFrom?: Date;
     dateTo?: Date;
@@ -46,8 +46,8 @@ export const factory = (crowi: Crowi): Router => {
   const validators = {
     auditLogBulkExport: [
       body('filters').exists({ checkFalsy: true }).isObject(),
-      body('filters.users').optional({ nullable: true }).isArray(),
-      body('filters.users.*').optional({ nullable: true }).isMongoId(),
+      body('filters.usernames').optional({ nullable: true }).isArray(),
+      body('filters.usernames.*').optional({ nullable: true }).isString(),
       body('filters.actions').optional({ nullable: true }).isArray(),
       body('filters.actions.*')
         .optional({ nullable: true })

+ 2 - 7
apps/app/src/features/audit-log-bulk-export/server/service/audit-log-bulk-export-job-cron/steps/exportAuditLogsToFsAsync.ts

@@ -100,16 +100,11 @@ export async function exportAuditLogsToFsAsync(
       query.createdAt.$lte = new Date(filters.dateTo);
     }
   }
-  if (filters.users && filters.users.length > 0) {
+  if (filters.usernames && filters.usernames.length > 0) {
     const User = mongoose.model<IUser>('User');
     const userIds = await User.find({
-      _id: { $in: filters.users },
+      username: { $in: filters.usernames },
     }).distinct('_id');
-    if (userIds.length === 0) {
-      throw new Error(
-        `No users found with userIDs: ${filters.users.join(', ')}`,
-      );
-    }
     query.user = { $in: userIds };
   }
 

+ 16 - 18
apps/app/src/features/audit-log-bulk-export/server/service/audit-log-bulk-export.integ.ts

@@ -100,10 +100,11 @@ describe('AuditLogBulkExportService', () => {
       });
 
       it('should create a job with user filters', async () => {
-        const filters: { users: string[]; actions: SupportedActionType[] } = {
-          users: [user._id.toString()],
-          actions: ['PAGE_CREATE'],
-        };
+        const filters: { usernames: string[]; actions: SupportedActionType[] } =
+          {
+            usernames: [user.username],
+            actions: ['PAGE_CREATE'],
+          };
 
         const jobId = await auditLogBulkExportService.createOrResetExportJob(
           filters,
@@ -113,9 +114,7 @@ describe('AuditLogBulkExportService', () => {
 
         const createdJob = await AuditLogBulkExportJob.findById(jobId);
         expect(createdJob?.filters.actions).toEqual(['PAGE_CREATE']);
-        expect(createdJob?.filters.users?.map(String)).toEqual([
-          user._id.toString(),
-        ]);
+        expect(createdJob?.filters.usernames).toEqual([user.username]);
       });
 
       it('should reset existing job when restartJob is true', async () => {
@@ -275,18 +274,17 @@ describe('AuditLogBulkExportService', () => {
 
   describe('filter canonicalization', () => {
     it('should generate same job for logically equivalent filters', async () => {
-      const validUserId1 = new mongoose.Types.ObjectId().toString();
-      const validUserId2 = new mongoose.Types.ObjectId().toString();
-
-      const filters1: { actions: SupportedActionType[]; users: string[] } = {
-        actions: ['PAGE_VIEW', 'PAGE_CREATE'],
-        users: [validUserId1, validUserId2],
-      };
+      const filters1: { actions: SupportedActionType[]; usernames: string[] } =
+        {
+          actions: ['PAGE_VIEW', 'PAGE_CREATE'],
+          usernames: ['alice', 'bob'],
+        };
 
-      const filters2: { actions: SupportedActionType[]; users: string[] } = {
-        actions: ['PAGE_CREATE', 'PAGE_VIEW'],
-        users: [validUserId2, validUserId1],
-      };
+      const filters2: { actions: SupportedActionType[]; usernames: string[] } =
+        {
+          actions: ['PAGE_CREATE', 'PAGE_VIEW'],
+          usernames: ['bob', 'alice'],
+        };
 
       await auditLogBulkExportService.createOrResetExportJob(
         filters1,

+ 2 - 2
apps/app/src/features/audit-log-bulk-export/server/service/audit-log-bulk-export.ts

@@ -30,8 +30,8 @@ export interface IAuditLogBulkExportService {
 function canonicalizeFilters(filters: IAuditLogBulkExportFilters) {
   const normalized: Record<string, unknown> = {};
 
-  if (filters.users?.length) {
-    normalized.users = filters.users.map(String).sort();
+  if (filters.usernames?.length) {
+    normalized.usernames = [...filters.usernames].sort();
   }
   if (filters.actions?.length) {
     normalized.actions = [...filters.actions].sort();