Skip to content

Commit

Permalink
[backend] WIP Update model: authorized members activation via entity(#…
Browse files Browse the repository at this point in the history
  • Loading branch information
marieflorescontact committed Jul 16, 2024
1 parent cd07267 commit af402d5
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8381,6 +8381,7 @@ type Mutation {
caseTemplateRelationDelete(id: ID!, toId: StixRef!, relationship_type: String!): CaseTemplate
caseIncidentAdd(input: CaseIncidentAddInput!): CaseIncident
caseIncidentDelete(id: ID!): ID
caseIncidentEditAuthorizedMembers(id: ID!, input: [MemberAccessInput!]): CaseIncident
caseRfiAdd(input: CaseRfiAddInput!): CaseRfi
caseRfiDelete(id: ID!): ID
caseRftAdd(input: CaseRftAddInput!): CaseRft
Expand Down
8 changes: 8 additions & 0 deletions opencti-platform/opencti-graphql/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12550,6 +12550,7 @@ export type Mutation = {
caseDelete?: Maybe<Scalars['ID']['output']>;
caseIncidentAdd?: Maybe<CaseIncident>;
caseIncidentDelete?: Maybe<Scalars['ID']['output']>;
caseIncidentEditAuthorizedMembers?: Maybe<CaseIncident>;
caseRfiAdd?: Maybe<CaseRfi>;
caseRfiDelete?: Maybe<Scalars['ID']['output']>;
caseRftAdd?: Maybe<CaseRft>;
Expand Down Expand Up @@ -13059,6 +13060,12 @@ export type MutationCaseIncidentDeleteArgs = {
};


export type MutationCaseIncidentEditAuthorizedMembersArgs = {
id: Scalars['ID']['input'];
input?: InputMaybe<Array<MemberAccessInput>>;
};


export type MutationCaseRfiAddArgs = {
input: CaseRfiAddInput;
};
Expand Down Expand Up @@ -34583,6 +34590,7 @@ export type MutationResolvers<ContextType = any, ParentType extends ResolversPar
caseDelete?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType, RequireFields<MutationCaseDeleteArgs, 'id'>>;
caseIncidentAdd?: Resolver<Maybe<ResolversTypes['CaseIncident']>, ParentType, ContextType, RequireFields<MutationCaseIncidentAddArgs, 'input'>>;
caseIncidentDelete?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType, RequireFields<MutationCaseIncidentDeleteArgs, 'id'>>;
caseIncidentEditAuthorizedMembers?: Resolver<Maybe<ResolversTypes['CaseIncident']>, ParentType, ContextType, RequireFields<MutationCaseIncidentEditAuthorizedMembersArgs, 'id'>>;
caseRfiAdd?: Resolver<Maybe<ResolversTypes['CaseRfi']>, ParentType, ContextType, RequireFields<MutationCaseRfiAddArgs, 'input'>>;
caseRfiDelete?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType, RequireFields<MutationCaseRfiDeleteArgs, 'id'>>;
caseRftAdd?: Resolver<Maybe<ResolversTypes['CaseRft']>, ParentType, ContextType, RequireFields<MutationCaseRftAddArgs, 'input'>>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { AuthContext, AuthUser } from '../../../types/user';
import { createEntity } from '../../../database/middleware';
import { createEntity, patchAttribute } from '../../../database/middleware';
import type { EntityOptions } from '../../../database/middleware-loader';
import { internalLoadById, listEntitiesPaginated, storeLoadById } from '../../../database/middleware-loader';
import { BUS_TOPICS } from '../../../config/conf';
import { ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey } from '../../../schema/general';
import { ABSTRACT_STIX_CORE_OBJECT, ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey } from '../../../schema/general';
import { notify } from '../../../database/redis';
import { now } from '../../../utils/format';
import { userAddIndividual } from '../../../domain/user';
Expand All @@ -12,10 +12,13 @@ import { upsertTemplateForCase } from '../case-domain';
import type { BasicStoreEntityCaseIncident } from './case-incident-types';
import { ENTITY_TYPE_CONTAINER_CASE_INCIDENT } from './case-incident-types';
import type { DomainFindById } from '../../../domain/domainTypes';
import type { CaseIncidentAddInput } from '../../../generated/graphql';
import type { CaseIncidentAddInput, MemberAccessInput } from '../../../generated/graphql';
import { isStixId } from '../../../schema/schemaUtils';
import { RELATION_OBJECT } from '../../../schema/stixRefRelationship';
import { FilterMode } from '../../../generated/graphql';
import { isValidMemberAccessRight } from '../../../utils/access';
import { containsValidAdmin } from '../../../utils/authorizedMembers';
import { FunctionalError } from '../../../config/errors';

export const findById: DomainFindById<BasicStoreEntityCaseIncident> = (context: AuthContext, user: AuthUser, caseIncidentId: string) => {
return storeLoadById(context, user, caseIncidentId, ENTITY_TYPE_CONTAINER_CASE_INCIDENT);
Expand Down Expand Up @@ -59,3 +62,34 @@ export const caseIncidentContainsStixObjectOrStixRelationship = async (context:
const caseIncidentFound = await findAll(context, user, args);
return caseIncidentFound.edges.length > 0;
};

export const caseIncidentEditAuthorizedMembers = async (
context: AuthContext,
user: AuthUser,
entityId: string,
input: MemberAccessInput[] | undefined | null
) => {
let authorized_members: { id: string, access_right: string }[] | null = null;

if (input) {
// validate input (validate access right) and remove duplicates
const filteredInput = input.filter((value, index, array) => {
return isValidMemberAccessRight(value.access_right) && array.findIndex((e) => e.id === value.id) === index;
});

const hasValidAdmin = await containsValidAdmin(
context,
filteredInput,
['KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS']
);
if (!hasValidAdmin) {
throw FunctionalError('It should have at least one valid member with admin access');
}

authorized_members = filteredInput.map(({ id, access_right }) => ({ id, access_right }));
}

const patch = { authorized_members };
const { element } = await patchAttribute(context, user, entityId, ENTITY_TYPE_CONTAINER_CASE_INCIDENT, patch);
return notify(BUS_TOPICS[ABSTRACT_STIX_CORE_OBJECT].EDIT_TOPIC, element, user);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Resolvers } from '../../../generated/graphql';
import { buildRefRelationKey } from '../../../schema/general';
import { RELATION_OBJECT_ASSIGNEE } from '../../../schema/stixRefRelationship';
import { stixDomainObjectDelete } from '../../../domain/stixDomainObject';
import { addCaseIncident, caseIncidentContainsStixObjectOrStixRelationship, findAll, findById } from './case-incident-domain';
import { addCaseIncident, caseIncidentContainsStixObjectOrStixRelationship, findAll, findById, caseIncidentEditAuthorizedMembers } from './case-incident-domain';
import { getAuthorizedMembers } from '../../../utils/authorizedMembers';

const caseIncidentResolvers: Resolvers = {
Expand All @@ -27,6 +27,9 @@ const caseIncidentResolvers: Resolvers = {
caseIncidentDelete: (_, { id }, context) => {
return stixDomainObjectDelete(context, context.user, id);
},
caseIncidentEditAuthorizedMembers: (_, { id, input }, context) => {
return caseIncidentEditAuthorizedMembers(context, context.user, id, input);
},
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,5 @@ input CaseIncidentAddInput {
type Mutation {
caseIncidentAdd(input: CaseIncidentAddInput!): CaseIncident @auth
caseIncidentDelete(id: ID!): ID @auth(for: [KNOWLEDGE_KNUPDATE_KNDELETE])
caseIncidentEditAuthorizedMembers(id: ID!, input:[MemberAccessInput!]): CaseIncident @auth(for: [KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS])
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ describe('Case Incident Response resolver standard behavior', () => {
});
expect(queryResult?.data?.stixDomainObjectEdit.fieldPatch.name).toEqual('Case - updated');
});
// TODO ADD context test even if i don't understand what it is?
it('should Case Incident Response deleted', async () => {
// Delete the case
await queryAsAdmin({
Expand All @@ -134,9 +133,75 @@ describe('Case Incident Response resolver standard behavior', () => {
});
});

describe('Case Incident Response authorized_members standard behavior', () => {
describe('Case Incident Response standard behavior with authorized_members activation from entity', () => {
let caseIncidentResponse: CaseIncident;
it('should Case Incident Response created', async () => {
// Create Case Incident Response
const caseIncidentResponseQueryResult = await queryAsAdmin({
query: CREATE_QUERY,
variables: {
input: {
name: 'Case Incident Response With Authorized Members'
}
}
});
caseIncidentResponse = caseIncidentResponseQueryResult?.data?.caseIncidentAdd;

// Activate Authorized members
const EDIT_AUTHORIZED_MEMBERS_QUERY = gql`
mutation CaseIncidentEditAuthorizedMembers(
$id: ID!
$input: [MemberAccessInput!]!
) {
caseIncidentEditAuthorizedMembers(id: $id, input: $input){
authorized_members {
id
name
entity_type
access_right
}
id
}
}
`;

await queryAsAdmin({
query: EDIT_AUTHORIZED_MEMBERS_QUERY,
variables: {
id: caseIncidentResponse.id,
input: [
{
id: ADMIN_USER.id,
access_right: 'admin'
}
]
}
});
expect(caseIncidentResponseQueryResult).not.toBeNull();
expect(caseIncidentResponseQueryResult?.data?.caseIncidentAdd.authorized_members).not.toBeUndefined();
expect(caseIncidentResponseQueryResult?.data?.caseIncidentAdd.authorized_members).toEqual([
{
id: ADMIN_USER.id,
access_right: 'admin'
}
]);
});
it('should Case Incident Response deleted', async () => {
// Delete the case
await queryAsAdmin({
query: DELETE_QUERY,
variables: { id: caseIncidentResponse.id },
});
// Verify is no longer found
const queryResult = await queryAsAdmin({ query: READ_QUERY, variables: { id: caseIncidentResponse.id } });
expect(queryResult).not.toBeNull();
expect(queryResult?.data?.caseIncident).toBeNull();
});
});

describe('Case Incident Response standard behavior with authorized_members activated via settings', () => {
let caseIncidentResponseAuthorizedMembers: CaseIncident;
it('should Case Incident Response created with authorized_members activated via settings', async () => {
it('should Case Incident Response created', async () => {
// Activate authorized members for IR
const ENTITY_SETTINGS_READ_QUERY_BY_TARGET_TYPE = gql`
query entitySettingsByTargetType($targetType: String!) {
Expand Down

0 comments on commit af402d5

Please sign in to comment.