Skip to content

Commit

Permalink
[backend] modify field patch to include file modification
Browse files Browse the repository at this point in the history
  • Loading branch information
JeremyCloarec committed Nov 29, 2024
1 parent c9cd068 commit 5ede59c
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8957,8 +8957,7 @@ type Mutation {
supportPackageDelete(id: ID!): ID
exclusionListContentAdd(input: ExclusionListContentAddInput!): ExclusionList
exclusionListFileAdd(input: ExclusionListFileAddInput!): ExclusionList
exclusionListFieldPatch(id: ID!, input: [EditInput!]!): ExclusionList
exclusionListFileUpdate(id: ID!, file: Upload!): ExclusionList
exclusionListFieldPatch(id: ID!, input: [EditInput!], file: Upload): ExclusionList
exclusionListDelete(id: ID!): ID
draftWorkspaceAdd(input: DraftWorkspaceAddInput!): DraftWorkspace
draftWorkspaceValidate(id: ID!): Work
Expand Down
3 changes: 3 additions & 0 deletions opencti-platform/opencti-graphql/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
"cache_max_size": 5000,
"cache_max_time": 2
},
"exclusion_list": {
"file_max_size": 10000000
},
"performance_logger": false,
"map_tile_server_dark": "https://map.opencti.io/styles/filigran-dark2/{z}/{x}/{y}.png",
"map_tile_server_light": "https://map.opencti.io/styles/filigran-light2/{z}/{x}/{y}.png",
Expand Down
13 changes: 3 additions & 10 deletions opencti-platform/opencti-graphql/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13526,7 +13526,6 @@ export type Mutation = {
exclusionListDelete?: Maybe<Scalars['ID']['output']>;
exclusionListFieldPatch?: Maybe<ExclusionList>;
exclusionListFileAdd?: Maybe<ExclusionList>;
exclusionListFileUpdate?: Maybe<ExclusionList>;
externalReferenceAdd?: Maybe<ExternalReference>;
externalReferenceEdit?: Maybe<ExternalReferenceEditMutations>;
feedAdd?: Maybe<Feed>;
Expand Down Expand Up @@ -14350,8 +14349,9 @@ export type MutationExclusionListDeleteArgs = {


export type MutationExclusionListFieldPatchArgs = {
file?: InputMaybe<Scalars['Upload']['input']>;
id: Scalars['ID']['input'];
input: Array<EditInput>;
input?: InputMaybe<Array<EditInput>>;
};


Expand All @@ -14360,12 +14360,6 @@ export type MutationExclusionListFileAddArgs = {
};


export type MutationExclusionListFileUpdateArgs = {
file: Scalars['Upload']['input'];
id: Scalars['ID']['input'];
};


export type MutationExternalReferenceAddArgs = {
input: ExternalReferenceAddInput;
};
Expand Down Expand Up @@ -36932,9 +36926,8 @@ export type MutationResolvers<ContextType = any, ParentType extends ResolversPar
eventRelationDelete?: Resolver<Maybe<ResolversTypes['Event']>, ParentType, ContextType, RequireFields<MutationEventRelationDeleteArgs, 'id' | 'relationship_type' | 'toId'>>;
exclusionListContentAdd?: Resolver<Maybe<ResolversTypes['ExclusionList']>, ParentType, ContextType, RequireFields<MutationExclusionListContentAddArgs, 'input'>>;
exclusionListDelete?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType, RequireFields<MutationExclusionListDeleteArgs, 'id'>>;
exclusionListFieldPatch?: Resolver<Maybe<ResolversTypes['ExclusionList']>, ParentType, ContextType, RequireFields<MutationExclusionListFieldPatchArgs, 'id' | 'input'>>;
exclusionListFieldPatch?: Resolver<Maybe<ResolversTypes['ExclusionList']>, ParentType, ContextType, RequireFields<MutationExclusionListFieldPatchArgs, 'id'>>;
exclusionListFileAdd?: Resolver<Maybe<ResolversTypes['ExclusionList']>, ParentType, ContextType, RequireFields<MutationExclusionListFileAddArgs, 'input'>>;
exclusionListFileUpdate?: Resolver<Maybe<ResolversTypes['ExclusionList']>, ParentType, ContextType, RequireFields<MutationExclusionListFileUpdateArgs, 'file' | 'id'>>;
externalReferenceAdd?: Resolver<Maybe<ResolversTypes['ExternalReference']>, ParentType, ContextType, RequireFields<MutationExternalReferenceAddArgs, 'input'>>;
externalReferenceEdit?: Resolver<Maybe<ResolversTypes['ExternalReferenceEditMutations']>, ParentType, ContextType, RequireFields<MutationExternalReferenceEditArgs, 'id'>>;
feedAdd?: Resolver<Maybe<ResolversTypes['Feed']>, ParentType, ContextType, RequireFields<MutationFeedAddArgs, 'input'>>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Readable } from 'stream';
import { BUS_TOPICS, isFeatureEnabled } from '../../config/conf';
import conf, { BUS_TOPICS, isFeatureEnabled } from '../../config/conf';
import { type FileUploadData, uploadToStorage } from '../../database/file-storage-helper';
import { deleteFile } from '../../database/file-storage';
import { createInternalObject, deleteInternalObject } from '../../domain/internalObject';
import { listEntitiesPaginated, storeLoadById } from '../../database/middleware-loader';
import type { AuthContext, AuthUser } from '../../types/user';
import { type BasicStoreEntityExclusionList, ENTITY_TYPE_EXCLUSION_LIST, type StoreEntityExclusionList } from './exclusionList-types';
import { type EditInput, type ExclusionListContentAddInput, type ExclusionListFileAddInput, type QueryExclusionListsArgs } from '../../generated/graphql';
import { type ExclusionListContentAddInput, type ExclusionListFileAddInput, type MutationExclusionListFieldPatchArgs, type QueryExclusionListsArgs } from '../../generated/graphql';
import { notify, redisUpdateExclusionListStatus } from '../../database/redis';
import { FunctionalError } from '../../config/errors';
import { updateAttribute } from '../../database/middleware';
Expand All @@ -15,6 +15,7 @@ import { publishUserAction } from '../../listener/UserActionListener';
const filePath = 'exclusionLists';

const isExclusionListEnabled = isFeatureEnabled('EXCLUSION_LIST');
const MAX_FILE_SIZE = conf.get('app:exclusion_list:file_max_size') ?? 10000000;

export const findById = (context: AuthContext, user: AuthUser, id: string) => {
return storeLoadById<BasicStoreEntityExclusionList>(context, user, id, ENTITY_TYPE_EXCLUSION_LIST);
Expand All @@ -28,8 +29,29 @@ const refreshExclusionListStatus = async () => {
await redisUpdateExclusionListStatus({ last_refresh_ask_date: (new Date()).toString() });
};

export const checkFileSize = async (createReadStream: () => Readable) => {
const uploadStream = createReadStream();
let byteLength = 0;
let fileTooHeavy = false;
// eslint-disable-next-line no-restricted-syntax
for await (const uploadChunk of uploadStream) {
byteLength += (uploadChunk as Buffer).byteLength;

if (byteLength > MAX_FILE_SIZE) {
fileTooHeavy = true;
break;
}

Check warning on line 43 in opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts

View check run for this annotation

Codecov / codecov/patch

opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts#L41-L43

Added lines #L41 - L43 were not covered by tests
}
uploadStream.destroy();

if (fileTooHeavy) {
throw FunctionalError('Exclusion list file too large', { maxFileSize: MAX_FILE_SIZE });
}

Check warning on line 49 in opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts

View check run for this annotation

Codecov / codecov/patch

opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts#L48-L49

Added lines #L48 - L49 were not covered by tests
};

const uploadExclusionListFile = async (context: AuthContext, user: AuthUser, exclusionListName: string, file: FileUploadData) => {
const fullFile = await file;
await checkFileSize(fullFile.createReadStream);
const exclusionFile = { ...fullFile, filename: `${exclusionListName}.txt` };
const { upload } = await uploadToStorage(context, user, filePath, exclusionFile, {});
return upload;
Expand Down Expand Up @@ -64,32 +86,36 @@ export const addExclusionListFile = async (context: AuthContext, user: AuthUser,
return storeAndCreateExclusionList(context, user, input, input.file);
};

export const fieldPatchExclusionList = async (context: AuthContext, user: AuthUser, id: string, input: EditInput[]) => {
export const fieldPatchExclusionList = async (context: AuthContext, user: AuthUser, args: MutationExclusionListFieldPatchArgs) => {
const { id, file, input } = args;
const exclusionList = await findById(context, user, id);
if (!exclusionList) {
throw FunctionalError(`Exclusion list ${id} cannot be found`);
}

const { element } = await updateAttribute(context, user, id, ENTITY_TYPE_EXCLUSION_LIST, input);
await refreshExclusionListStatus();
await publishUserAction({
user,
event_type: 'mutation',
event_scope: 'update',
event_access: 'administration',
message: `updates \`${input.map((i) => i.key).join(', ')}\` for exclusion list \`${element.name}\``,
context_data: { id, entity_type: ENTITY_TYPE_EXCLUSION_LIST, input }
});
return notify(BUS_TOPICS[ENTITY_TYPE_EXCLUSION_LIST].EDIT_TOPIC, element, user);
};
if (file) {
await uploadExclusionListFile(context, user, exclusionList.name, file);
}
let element;
if (input) {
const { updatedElement } = await updateAttribute(context, user, id, ENTITY_TYPE_EXCLUSION_LIST, input);
element = updatedElement;
}

Check warning on line 103 in opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts

View check run for this annotation

Codecov / codecov/patch

opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts#L101-L103

Added lines #L101 - L103 were not covered by tests

export const fileUpdateExclusionList = async (context: AuthContext, user: AuthUser, id: string, file: FileUploadData) => {
const exclusionList = await findById(context, user, id);
if (!exclusionList) {
throw FunctionalError(`Exclusion list ${id} cannot be found`);
if (file || (input && input.some((i) => i.key === 'enabled'))) {
await refreshExclusionListStatus();
}
if (element) {
await publishUserAction({
user,
event_type: 'mutation',
event_scope: 'update',
event_access: 'administration',
message: `updates \`${input?.map((i) => i.key).join(', ')}\` for exclusion list \`${element.name}\``,
context_data: { id, entity_type: ENTITY_TYPE_EXCLUSION_LIST, input }
});
return notify(BUS_TOPICS[ENTITY_TYPE_EXCLUSION_LIST].EDIT_TOPIC, element, user);
}

Check warning on line 118 in opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts

View check run for this annotation

Codecov / codecov/patch

opencti-platform/opencti-graphql/src/modules/exclusionList/exclusionList-domain.ts#L109-L118

Added lines #L109 - L118 were not covered by tests
await uploadExclusionListFile(context, user, exclusionList.name, file);
await refreshExclusionListStatus();
return exclusionList;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Resolvers } from '../../generated/graphql';
import { findById, findAll, addExclusionListContent, addExclusionListFile, deleteExclusionList, fieldPatchExclusionList, fileUpdateExclusionList } from './exclusionList-domain';
import { findById, findAll, addExclusionListContent, addExclusionListFile, deleteExclusionList, fieldPatchExclusionList } from './exclusionList-domain';

const exclusionListResolver: Resolvers = {
Query: {
Expand All @@ -13,11 +13,8 @@ const exclusionListResolver: Resolvers = {
exclusionListFileAdd: (_, { input }, context) => {
return addExclusionListFile(context, context.user, input);
},
exclusionListFieldPatch: (_, { id, input }, context) => {
return fieldPatchExclusionList(context, context.user, id, input);
},
exclusionListFileUpdate: (_, { id, file }, context) => {
return fileUpdateExclusionList(context, context.user, id, file);
exclusionListFieldPatch: (_, args, context) => {
return fieldPatchExclusionList(context, context.user, args);
},
exclusionListDelete: (_, { id }, context) => {
return deleteExclusionList(context, context.user, id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ type Query {
type Mutation {
exclusionListContentAdd(input: ExclusionListContentAddInput!): ExclusionList @auth(for: [SETTINGS_SETCUSTOMIZATION])
exclusionListFileAdd(input: ExclusionListFileAddInput!): ExclusionList @auth(for: [SETTINGS_SETCUSTOMIZATION])
exclusionListFieldPatch(id: ID!, input: [EditInput!]!): ExclusionList @auth(for: [SETTINGS_SETCUSTOMIZATION])
exclusionListFileUpdate(id: ID!, file: Upload!): ExclusionList @auth(for: [SETTINGS_SETCUSTOMIZATION])
exclusionListFieldPatch(id: ID!, input: [EditInput!], file: Upload): ExclusionList @auth(for: [SETTINGS_SETCUSTOMIZATION])
exclusionListDelete(id: ID!): ID @auth(for: [SETTINGS_SETCUSTOMIZATION])
}
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ const validateIndicatorPattern = async (context: AuthContext, user: AuthUser, pa
const exclusionListCheck = await checkObservableValue(observableValues[i]);
if (exclusionListCheck) {
throw FunctionalError(`Indicator of type ${patternType} is contained in exclusion list.`, {
doc_code: 'INDICATOR_FORMAT_EXCLUDED',
doc_code: 'INDICATOR_PATTERN_EXCLUDED',

Check warning on line 232 in opencti-platform/opencti-graphql/src/modules/indicator/indicator-domain.ts

View check run for this annotation

Codecov / codecov/patch

opencti-platform/opencti-graphql/src/modules/indicator/indicator-domain.ts#L231-L232

Added lines #L231 - L232 were not covered by tests
excludedValue: exclusionListCheck.value,
exclusionList: exclusionListCheck.listId
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ const CREATE_FILE_MUTATION = gql`
}
`;

const UPDATE_FILE_MUTATION = gql`
mutation exclusionListFileUpdate($id: ID!, $file: Upload!) {
exclusionListFileUpdate(id: $id, file: $file) {
const FIELD_PATCH_MUTATION = gql`
mutation exclusionListFileUpdate($id: ID!, $input: [EditInput!], $file: Upload) {
exclusionListFieldPatch(id: $id, input: $input, file: $file) {
id
file_id
exclusion_list_entity_types
Expand Down Expand Up @@ -159,7 +159,7 @@ describe('Exclusion list resolver', () => {
// Update file of exclusion list
const upload = createUploadFile('./tests/data/exclusionLists/', 'testFileExclusionListUpdate.txt');
await queryAsAdminWithSuccess({
query: UPDATE_FILE_MUTATION,
query: FIELD_PATCH_MUTATION,
variables: {
id: exclusionListFileResponse.id,
file: upload
Expand Down

0 comments on commit 5ede59c

Please sign in to comment.