@@ -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.
@@ -782,7 +926,6 @@ const startMigration = async (req: Request): Promise<any> => {
782926 }
783927} ;
784928
785-
786929const getLogs = async ( req : Request ) : Promise < any > => {
787930 const projectId = req ?. params ?. projectId ? path ?. basename ( req . params . projectId ) : "" ;
788931 const stackId = req ?. params ?. stackId ? path ?. basename ( req . params . stackId ) : "" ;
@@ -791,9 +934,7 @@ const getLogs = async (req: Request): Promise<any> => {
791934 const stopIndex = startIndex + limit ;
792935 const searchText = req ?. params ?. searchText ?? null ;
793936 const filter = req ?. params ?. filter ?? "all" ;
794-
795937 const srcFunc = "getLogs" ;
796-
797938 if (
798939 ! projectId ||
799940 ! stackId ||
@@ -802,40 +943,44 @@ const getLogs = async (req: Request): Promise<any> => {
802943 ) {
803944 throw new BadRequestError ( "Invalid projectId or stackId" ) ;
804945 }
805-
806946 try {
807947 const mainPath = process ?. cwd ( ) ?. split ( "migration-v2" ) ?. [ 0 ] ;
808948 if ( ! mainPath ) {
809949 throw new BadRequestError ( "Invalid application path" ) ;
810950 }
811-
812951 const logsDir = path ?. join ( mainPath , "migration-v2" , "api" , "logs" ) ;
813952 const loggerPath = path ?. join ( logsDir , projectId , `${ stackId } .log` ) ;
814953 const absolutePath = path ?. resolve ( loggerPath ) ;
815-
816954 if ( ! absolutePath ?. startsWith ( logsDir ) ) {
817955 throw new BadRequestError ( "Access to this file is not allowed." ) ;
818956 }
819-
820957 if ( fs . existsSync ( absolutePath ) ) {
958+ let index = 0 ;
821959 const logs = await fs . promises . readFile ( absolutePath , "utf8" ) ;
822960 let logEntries = logs
823961 ?. split ( "\n" )
824962 ?. map ( ( line ) => {
825963 try {
826- return line ? JSON ?. parse ( line ) : null ;
964+ const parsedLine = JSON ?. parse ( line )
965+ parsedLine [ 'id' ] = index ;
966+ ++ index ;
967+ return parsedLine ? parsedLine : null ;
827968 } catch ( error ) {
828969 return null ;
829970 }
830971 } )
831972 ?. filter ?.( ( entry ) => entry !== null ) ;
832-
833973 if ( ! logEntries ?. length ) {
834974 return { logs : [ ] , total : 0 } ;
835975 }
836-
976+ const filterOptions = Array ?. from ( new Set ( logEntries ?. map ( ( log ) => log ?. level ) ) ) ;
977+ const auditStartIndex = logEntries ?. findIndex ?.( log => log ?. message ?. includes ( "Starting audit process" ) ) ;
978+ const auditEndIndex = logEntries ?. findIndex ?.( log => log ?. message ?. includes ( "Audit process completed" ) ) ;
979+ logEntries = [
980+ ...logEntries . slice ( 0 , auditStartIndex ) ,
981+ ...logEntries . slice ( auditEndIndex + 1 )
982+ ]
837983 logEntries = logEntries ?. slice ?.( 1 , logEntries ?. length - 2 ) ;
838-
839984 if ( filter !== "all" ) {
840985 const filters = filter ?. split ( "-" ) ?? [ ] ;
841986 logEntries = logEntries ?. filter ( ( log ) => {
@@ -846,17 +991,17 @@ const getLogs = async (req: Request): Promise<any> => {
846991 } ) ;
847992 } ) ;
848993 }
849-
850994 if ( searchText && searchText !== "null" ) {
851995 logEntries = logEntries ?. filter ?.( ( log ) =>
852996 matchesSearchText ( log , searchText )
853997 ) ;
854998 }
855-
856999 const paginatedLogs = logEntries ?. slice ?.( startIndex , stopIndex ) ?? [ ] ;
8571000 return {
8581001 logs : paginatedLogs ,
8591002 total : logEntries ?. length ?? 0 ,
1003+ filterOptions : filterOptions ,
1004+ status : HTTP_CODES ?. OK
8601005 } ;
8611006 } else {
8621007 logger . error ( getLogMessage ( srcFunc , HTTP_TEXTS . LOGS_NOT_FOUND ) ) ;
@@ -971,4 +1116,5 @@ export const migrationService = {
9711116 getLogs,
9721117 createSourceLocales,
9731118 updateLocaleMapper,
1119+ getAuditData
9741120} ;
0 commit comments