Skip to content

Commit

Permalink
Support importing filters/charts from v2
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryAstafyev committed Sep 7, 2023
1 parent 0667ff6 commit 6b29bf7
Show file tree
Hide file tree
Showing 13 changed files with 275 additions and 21 deletions.
15 changes: 15 additions & 0 deletions application/client/src/app/service/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class Service extends Implementation {
});
return Promise.resolve();
}

public files(): {
getByPath(filenames: string[]): Promise<File[]>;
getByPathWithCache(filenames: string[]): Promise<File[]>;
Expand All @@ -57,6 +58,7 @@ export class Service extends Implementation {
): Promise<{ name: string; filename: string; parent: string; ext: string }>;
cp(src: string, dest: string): Promise<void>;
copy(files: string[], dest: string): Promise<void>;
read(filename: string): Promise<string>;
select: {
any(): Promise<File[]>;
dlt(): Promise<File[]>;
Expand Down Expand Up @@ -249,6 +251,19 @@ export class Service extends Implementation {
return Promise.resolve();
});
},
read: (filename: string): Promise<string> => {
return Requests.IpcRequest.send(
Requests.File.Read.Response,
new Requests.File.Read.Request({
file: filename,
}),
).then((response) => {
if (response.error !== undefined) {
return Promise.reject(new Error(response.error));
}
return Promise.resolve(response.text as string);
});
},
select: {
any: (): Promise<File[]> => {
return request(undefined, `dlt,pcapng,txt,log,logs`);
Expand Down
45 changes: 45 additions & 0 deletions application/client/src/app/service/history/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import { SetupLogger, LoggerInterface } from '@platform/entity/logger';
import { Equal, Empty } from '@platform/types/env/types';
import { Subject, Subscriber } from '@platform/env/subscription';
import { StorageCollections } from './storage.collections';
import { unique } from '@platform/env/sequence';
import { FilterRequest } from '@service/session/dependencies/search/filters/request';
import { ChartRequest } from '@service/session/dependencies/search/charts/request';

import * as obj from '@platform/env/obj';

Expand Down Expand Up @@ -62,6 +65,48 @@ export class Collections implements EntryConvertable, Equal<Collections>, Empty
}
}

static fromV2(smth: { [key: string]: any }, storage: StorageCollections): Collections {
const uuid = unique();
obj.isObject(smth);
const filters: FilterRequest[] = [];
if (smth['filters'] instanceof Array) {
smth['filters'].forEach((smth) => {
const validFilter = FilterRequest.fromV2(smth);
if (validFilter instanceof Error) {
return;
}
filters.push(validFilter);
});
}
const charts: ChartRequest[] = [];
if (smth['charts'] instanceof Array) {
smth['charts'].forEach((smth) => {
const validChart = ChartRequest.fromV2(smth);
if (validChart instanceof Error) {
return;
}
charts.push(validChart);
});
}
return new Collections(
`Collections:${uuid}`,
{
name: '-',
last: Date.now(),
created: Date.now(),
used: 1,
uuid: uuid,
preset: false,
relations: [],
origin: undefined,
entries: filters
.map((f) => f.asJsonField())
.concat(charts.map((d) => d.asJsonField())),
},
storage,
);
}

static fromMinifiedStr(src: { [key: string]: number | string }): ICollection {
return {
name: obj.getAsNotEmptyString(src, 'n'),
Expand Down
104 changes: 85 additions & 19 deletions application/client/src/app/service/history/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { Subject } from '@platform/env/subscription';
import { unique } from '@platform/env/sequence';
import { error } from '@platform/log/utils';
import { bridge } from '@service/bridge';
import { lockers, Locker } from '@ui/service/lockers';
import { scope } from '@platform/env/scope';

import * as obj from '@platform/env/obj';

export class Provider implements EntryConvertable {
protected collections: Collections[] = [];
Expand All @@ -16,6 +20,83 @@ export class Provider implements EntryConvertable {
collections: StorageCollections;
definitions: StorageDefinitions;
};
protected importFromC2Version(filename: string, err: Error): Promise<string[]> {
const logger = scope.getLogger('ImporterFiltersFromV2');
return new Promise((resolve, reject) => {
const message = lockers.lock(
new Locker(
false,
`Fail to read from file due error: ${err.message.split(/[\n\r]/gi)[0]}`,
)
.set()
.buttons([
{
caption: `Try read as Chipmunk v2 filters`,
handler: () => {
message.popup.close();
bridge
.files()
.read(filename)
.then((text: string) => {
try {
const parsed = JSON.parse(text);
obj.isObject(parsed);
this.collections = [
Collections.fromV2(
parsed,
this.storage.collections,
),
];
this.definitions = [];
resolve(this.orderAfterImport());
} catch (e) {
logger.error(error(e));
reject(new Error(error(e)));
}
})
.catch((err: Error) => {
logger.error(err.message);
reject(err);
});
},
},
{
caption: `Cancel`,
handler: () => {
message.popup.close();
resolve([]);
},
},
])
.end(),
{
closable: false,
},
);
});
}

protected orderAfterImport(): string[] {
this.collections = this.collections.map((col) => {
// Reassign uuids of definitions as soon as it will be diffrent in case
// if both users have same source
col.relations = col.relations.map((uuid) => {
let target = this.definitions.find((d) => d.uuid === uuid);
if (target === undefined) {
return uuid;
}
target = this.storage.definitions.update(target);
return target.uuid;
});
return col;
});
const uuids: string[] = this.collections.map((collection) => collection.uuid);
this.storage.definitions.add(this.definitions);
this.storage.collections.add(this.collections);
this.collections = [];
this.definitions = [];
return uuids;
}

constructor(collections: StorageCollections, definitions: StorageDefinitions) {
this.storage = {
Expand Down Expand Up @@ -70,25 +151,10 @@ export class Provider implements EntryConvertable {
if (error instanceof Error) {
return Promise.reject(error);
}
this.collections = this.collections.map((col) => {
// Reassign uuids of definitions as soon as it will be diffrent in case
// if both users have same source
col.relations = col.relations.map((uuid) => {
let target = this.definitions.find((d) => d.uuid === uuid);
if (target === undefined) {
return uuid;
}
target = this.storage.definitions.update(target);
return target.uuid;
});
return col;
});
const uuid: string[] = this.collections.map(collection => collection.uuid);
this.storage.definitions.add(this.definitions);
this.storage.collections.add(this.collections);
this.collections = [];
this.definitions = [];
return uuid;
return this.orderAfterImport();
})
.catch((err: Error) => {
return this.importFromC2Version(filename, err);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ export class ChartRequest
}
}

public static fromV2(smth: { [key: string]: unknown }): ChartRequest | Error {
try {
return new ChartRequest({
uuid: obj.getAsString(smth, 'guid'),
filter: obj.getAsNotEmptyString(smth, 'request'),
color: obj.getAsNotEmptyString(smth, 'color'),
active: obj.getAsBool(smth, 'active'),
});
} catch (e) {
return new Error(error(e));
}
}

public readonly definition: Definition;
public readonly updated: Subject<UpdateEvent> = new Subject<UpdateEvent>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,30 @@ export class FilterRequest
}
}

public static fromV2(smth: { [key: string]: unknown }): FilterRequest | Error {
try {
const flags = obj.getAsObj(smth, 'flags');
return new FilterRequest({
uuid: obj.getAsString(smth, 'guid'),
filter: {
filter: obj.getAsNotEmptyString(smth, 'request'),
flags: {
cases: obj.getAsBool(flags, 'casesensitive'),
word: obj.getAsBool(flags, 'wholeword'),
reg: obj.getAsBool(flags, 'regexp'),
},
},
colors: {
color: obj.getAsNotEmptyString(smth, 'color'),
background: obj.getAsNotEmptyString(smth, 'background'),
},
active: obj.getAsBool(smth, 'active'),
});
} catch (e) {
return new Error(error(e));
}
}

static isValid(filter: IFilter): boolean {
return (
getFilterError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
text-align: right;
padding: 12px 0 6px 0;
width: 100%;
white-space: nowrap;
& button {
display: inline-block;
margin-left: 12px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ export class Providers {
}),
);
};

return {
import: (): void => {
bridge
Expand Down
9 changes: 9 additions & 0 deletions application/holder/src/service/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ export class Service extends Implementation {
RequestHandlers.File.Copy.handler,
),
);
this.register(
electron
.ipc()
.respondent(
this.getName(),
Requests.File.Read.Request,
RequestHandlers.File.Read.handler,
),
);
this.register(
electron
.ipc()
Expand Down
1 change: 1 addition & 0 deletions application/holder/src/service/bridge/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * as Exists from './exists';
export * as Name from './name';
export * as Copy from './copy';
export * as CopyFile from './copyfile';
export * as Read from './read';
44 changes: 44 additions & 0 deletions application/holder/src/service/bridge/file/read.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { CancelablePromise } from 'platform/env/promise';
import { Logger } from 'platform/log';

import * as fs from 'fs';
import * as Requests from 'platform/ipc/request';

export const handler = Requests.InjectLogger<
Requests.File.Read.Request,
CancelablePromise<Requests.File.Read.Response>
>(
(
_log: Logger,
request: Requests.File.Read.Request,
): CancelablePromise<Requests.File.Read.Response> => {
return new CancelablePromise((resolve, _reject) => {
if (!fs.existsSync(request.file)) {
return resolve(
new Requests.File.Read.Response({
text: undefined,
error: `File ${request.file} doesn't exist`,
}),
);
}
fs.promises
.readFile(request.file, { encoding: 'utf-8' })
.then((text: string) => {
return resolve(
new Requests.File.Read.Response({
text,
error: undefined,
}),
);
})
.catch((err: Error) => {
return resolve(
new Requests.File.Read.Response({
text: undefined,
error: `Fail to read file ${request.file}: ${err.message}`,
}),
);
});
});
},
);
8 changes: 7 additions & 1 deletion application/holder/src/service/storage/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ export type Reader = (key: string) => Promise<string>;
export class Entries {
static from(str: string, storageKey: string, logger: Logger): Map<string, Entry> {
const entries = new Map<string, Entry>();
(JSON.parse(str) as Entry[]).forEach((entry) => {
const parsed = JSON.parse(str) as Entry[];
if (!(parsed instanceof Array)) {
throw new Error(
`Invalid format: expecting an Entry[], but has been gotten: ${typeof parsed}`,
);
}
parsed.forEach((entry) => {
if (typeof entry['uuid'] !== 'string' || entry['uuid'].trim() === '') {
logger.warn(`Storage "${storageKey}" includes entries without valid "uuid"`);
return;
Expand Down
1 change: 1 addition & 0 deletions application/platform/ipc/request/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * as Exists from './exists';
export * as Name from './name';
export * as Copy from './copy';
export * as CopyFile from './copyfile';
export * as Read from './read';
Loading

0 comments on commit 6b29bf7

Please sign in to comment.