@@ -7,6 +7,7 @@ import https from "../utils/https.utils.js";
77import { LoginServiceType } from "../models/types.js" ;
88import getAuthtoken from "../utils/auth.utils.js" ;
99import logger from "../utils/logger.js" ;
10+ import { GET_AUDIT_DATA } from "../constants/index.js" ;
1011import {
1112 HTTP_TEXTS ,
1213 HTTP_CODES ,
@@ -118,12 +119,10 @@ const createTestStack = async (req: Request): Promise<LoginServiceType> => {
118119 }
119120 return {
120121 data : {
121- data : res . data ,
122- url : `${
123- config . CS_URL [ token_payload ?. region as keyof typeof config . CS_URL ]
124- } /stack/${ res . data . stack . api_key } /dashboard`,
122+ data : res ?. data ,
123+ url : `${ config ?. CS_URL [ token_payload ?. region as keyof typeof config . CS_URL ] } /stack/${ res ?. data ?. stack ?. api_key } /dashboard` ,
125124 } ,
126- status : res . status ,
125+ status : res ? .status ,
127126 } ;
128127 } catch ( error : any ) {
129128 logger . error (
@@ -135,13 +134,158 @@ const createTestStack = async (req: Request): Promise<LoginServiceType> => {
135134 )
136135 ) ;
137136
137+ throw new ExceptionFunction (
138+ error ?. message || HTTP_TEXTS ?. INTERNAL_ERROR ,
139+ error ?. statusCode || error ?. status || HTTP_CODES . SERVER_ERROR
140+ ) ;
141+ }
142+ } ;
143+
144+ const getAuditData = async ( req : Request ) : Promise < any > => {
145+ const projectId = path ?. basename ( req ?. params ?. projectId ) ;
146+ const stackId = path ?. basename ( req ?. params ?. stackId ) ;
147+ const moduleName = path . basename ( req ?. params ?. moduleName ) ;
148+ const limit = parseInt ( req ?. params ?. limit ) ;
149+ const startIndex = parseInt ( req ?. params ?. startIndex ) ;
150+ const stopIndex = startIndex + limit ;
151+ const searchText = req ?. params ?. searchText ;
152+ const filter = req ?. params ?. filter ;
153+ const srcFunc = "getAuditData" ;
154+
155+ if ( projectId ?. includes ( '..' ) || stackId ?. includes ( '..' ) || moduleName ?. includes ( '..' ) ) {
156+ throw new BadRequestError ( "Invalid projectId, stackId, or moduleName" ) ;
157+ }
158+
159+ try {
160+ const mainPath = process ?. cwd ( ) ?. split ?.( GET_AUDIT_DATA ?. MIGRATION ) ?. [ 0 ] ;
161+ const logsDir = path . join ( mainPath , GET_AUDIT_DATA ?. MIGRATION , GET_AUDIT_DATA ?. API_DIR , GET_AUDIT_DATA ?. MIGRATION_DATA_DIR ) ;
162+
163+ const stackFolders = fs . readdirSync ( logsDir ) ;
164+
165+ const stackFolder = stackFolders ?. find ( folder => folder ?. startsWith ?.( stackId ) ) ;
166+ if ( ! stackFolder ) {
167+ throw new BadRequestError ( "Migration data not found for this stack" ) ;
168+ }
169+
170+ const auditLogPath = path ?. resolve ( logsDir , stackFolder , GET_AUDIT_DATA ?. LOGS_DIR , GET_AUDIT_DATA ?. AUDIT_DIR , GET_AUDIT_DATA ?. AUDIT_REPORT ) ;
171+ if ( ! fs . existsSync ( auditLogPath ) ) {
172+ throw new BadRequestError ( "Audit log path not found" ) ;
173+ }
174+
175+
176+ // Read and parse the JSON file for the module
177+ const filePath = path ?. resolve ( auditLogPath , `${ moduleName } .json` ) ;
178+ let fileData ;
179+ if ( fs ?. existsSync ( filePath ) ) {
180+ const fileContent = await fsPromises . readFile ( filePath , 'utf8' ) ;
181+ try {
182+ if ( typeof fileContent === 'string' ) {
183+ fileData = JSON ?. parse ( fileContent ) ;
184+ }
185+ } catch ( error ) {
186+ logger . error ( `Error parsing JSON from file ${ filePath } :` , error ) ;
187+ throw new BadRequestError ( 'Invalid JSON format in audit file' ) ;
188+ }
189+ }
190+
191+ if ( ! fileData ) {
192+ throw new BadRequestError ( `No audit data found for module: ${ moduleName } ` ) ;
193+ }
194+ let transformedData = transformAndFlattenData ( fileData ) ;
195+ if ( filter != GET_AUDIT_DATA ?. FILTERALL ) {
196+ const filters = filter ?. split ( "-" ) ;
197+ moduleName === 'Entries_Select_feild' ? transformedData = transformedData ?. filter ( ( log ) => {
198+ return filters ?. some ( ( filter ) => {
199+ return (
200+ log ?. display_type ?. toLowerCase ( ) ?. includes ( filter ?. toLowerCase ( ) )
201+ ) ;
202+ } ) ;
203+ } ) : transformedData = transformedData ?. filter ( ( log ) => {
204+ return filters ?. some ( ( filter ) => {
205+ return (
206+ log ?. data_type ?. toLowerCase ( ) ?. includes ( filter ?. toLowerCase ( ) )
207+ ) ;
208+ } ) ;
209+ } ) ;
210+
211+ }
212+ if ( searchText && searchText !== null && searchText !== "null" ) {
213+ transformedData = transformedData ?. filter ( ( item : any ) => {
214+ return Object ?. values ( item ) ?. some ( value =>
215+ value &&
216+ typeof value === 'string' &&
217+ value ?. toLowerCase ?.( ) ?. includes ( searchText ?. toLowerCase ( ) )
218+ ) ;
219+ } ) ;
220+ }
221+ const paginatedData = transformedData ?. slice ?.( startIndex , stopIndex ) ;
222+
223+ return {
224+ data : paginatedData ,
225+ totalCount : transformedData ?. length ,
226+ status : HTTP_CODES ?. OK
227+ } ;
228+
229+ } catch ( error : any ) {
230+ logger . error (
231+ getLogMessage (
232+ srcFunc ,
233+ `Error getting audit log data for module: ${ moduleName } ` ,
234+ error
235+ )
236+ ) ;
138237 throw new ExceptionFunction (
139238 error ?. message || HTTP_TEXTS . INTERNAL_ERROR ,
140239 error ?. statusCode || error ?. status || HTTP_CODES . SERVER_ERROR
141240 ) ;
142241 }
143242} ;
243+ /**
244+ * Transforms and flattens nested data structure into an array of items
245+ * with sequential tuid values
246+ */
247+ const transformAndFlattenData = ( data : any ) : Array < { [ key : string ] : any , id : number } > => {
248+ try {
249+ const flattenedItems : Array < { [ key : string ] : any } > = [ ] ;
144250
251+ // Handle the data based on its structure
252+ if ( Array . isArray ( data ) ) {
253+ // If data is already an array, use it directly
254+ data ?. forEach ( ( item , index ) => {
255+ flattenedItems ?. push ( {
256+ ...item ?? { } ,
257+ uid : item ?. uid || `item-${ index } `
258+ } ) ;
259+ } ) ;
260+ } else if ( typeof data === 'object' && data !== null ) {
261+ Object ?. entries ?.( data ) ?. forEach ( ( [ key , value ] ) => {
262+ if ( Array . isArray ( value ) ) {
263+ value ?. forEach ( ( item , index ) => {
264+ flattenedItems ?. push ( {
265+ ...item ?? { } ,
266+ parentKey : key ,
267+ uid : item ?. uid || `${ key } -${ index } `
268+ } ) ;
269+ } ) ;
270+ } else if ( typeof value === 'object' && value !== null ) {
271+ flattenedItems ?. push ( {
272+ ...value ,
273+ key,
274+ uid : ( value as any ) ?. uid || key
275+ } ) ;
276+ }
277+ } ) ;
278+ }
279+
280+ return flattenedItems ?. map ( ( item , index ) => ( {
281+ ...item ?? { } ,
282+ id : index + 1
283+ } ) ) ;
284+ } catch ( error ) {
285+ console . error ( 'Error transforming data:' , error ) ;
286+ return [ ] ;
287+ }
288+ } ;
145289/**
146290 * Deletes a test stack.
147291 * @param req - The request object.
@@ -794,7 +938,6 @@ const startMigration = async (req: Request): Promise<any> => {
794938 }
795939} ;
796940
797-
798941const getLogs = async ( req : Request ) : Promise < any > => {
799942 const projectId = req ?. params ?. projectId ? path ?. basename ( req . params . projectId ) : "" ;
800943 const stackId = req ?. params ?. stackId ? path ?. basename ( req . params . stackId ) : "" ;
@@ -803,9 +946,7 @@ const getLogs = async (req: Request): Promise<any> => {
803946 const stopIndex = startIndex + limit ;
804947 const searchText = req ?. params ?. searchText ?? null ;
805948 const filter = req ?. params ?. filter ?? "all" ;
806-
807949 const srcFunc = "getLogs" ;
808-
809950 if (
810951 ! projectId ||
811952 ! stackId ||
@@ -814,40 +955,44 @@ const getLogs = async (req: Request): Promise<any> => {
814955 ) {
815956 throw new BadRequestError ( "Invalid projectId or stackId" ) ;
816957 }
817-
818958 try {
819959 const mainPath = process ?. cwd ( ) ?. split ( "migration-v2" ) ?. [ 0 ] ;
820960 if ( ! mainPath ) {
821961 throw new BadRequestError ( "Invalid application path" ) ;
822962 }
823-
824963 const logsDir = path ?. join ( mainPath , "migration-v2" , "api" , "logs" ) ;
825964 const loggerPath = path ?. join ( logsDir , projectId , `${ stackId } .log` ) ;
826965 const absolutePath = path ?. resolve ( loggerPath ) ;
827-
828966 if ( ! absolutePath ?. startsWith ( logsDir ) ) {
829967 throw new BadRequestError ( "Access to this file is not allowed." ) ;
830968 }
831-
832969 if ( fs . existsSync ( absolutePath ) ) {
970+ let index = 0 ;
833971 const logs = await fs . promises . readFile ( absolutePath , "utf8" ) ;
834972 let logEntries = logs
835973 ?. split ( "\n" )
836974 ?. map ( ( line ) => {
837975 try {
838- return line ? JSON ?. parse ( line ) : null ;
976+ const parsedLine = JSON ?. parse ( line )
977+ parsedLine [ 'id' ] = index ;
978+ ++ index ;
979+ return parsedLine ? parsedLine : null ;
839980 } catch ( error ) {
840981 return null ;
841982 }
842983 } )
843984 ?. filter ?.( ( entry ) => entry !== null ) ;
844-
845985 if ( ! logEntries ?. length ) {
846986 return { logs : [ ] , total : 0 } ;
847987 }
848-
988+ const filterOptions = Array ?. from ( new Set ( logEntries ?. map ( ( log ) => log ?. level ) ) ) ;
989+ const auditStartIndex = logEntries ?. findIndex ?.( log => log ?. message ?. includes ( "Starting audit process" ) ) ;
990+ const auditEndIndex = logEntries ?. findIndex ?.( log => log ?. message ?. includes ( "Audit process completed" ) ) ;
991+ logEntries = [
992+ ...logEntries . slice ( 0 , auditStartIndex ) ,
993+ ...logEntries . slice ( auditEndIndex + 1 )
994+ ]
849995 logEntries = logEntries ?. slice ?.( 1 , logEntries ?. length - 2 ) ;
850-
851996 if ( filter !== "all" ) {
852997 const filters = filter ?. split ( "-" ) ?? [ ] ;
853998 logEntries = logEntries ?. filter ( ( log ) => {
@@ -858,17 +1003,17 @@ const getLogs = async (req: Request): Promise<any> => {
8581003 } ) ;
8591004 } ) ;
8601005 }
861-
8621006 if ( searchText && searchText !== "null" ) {
8631007 logEntries = logEntries ?. filter ?.( ( log ) =>
8641008 matchesSearchText ( log , searchText )
8651009 ) ;
8661010 }
867-
8681011 const paginatedLogs = logEntries ?. slice ?.( startIndex , stopIndex ) ?? [ ] ;
8691012 return {
8701013 logs : paginatedLogs ,
8711014 total : logEntries ?. length ?? 0 ,
1015+ filterOptions : filterOptions ,
1016+ status : HTTP_CODES ?. OK
8721017 } ;
8731018 } else {
8741019 logger . error ( getLogMessage ( srcFunc , HTTP_TEXTS . LOGS_NOT_FOUND ) ) ;
@@ -983,4 +1128,5 @@ export const migrationService = {
9831128 getLogs,
9841129 createSourceLocales,
9851130 updateLocaleMapper,
1131+ getAuditData
9861132} ;
0 commit comments