Skip to content

Commit 5b36af0

Browse files
[backend] WIP Update model: authorized members activation via entity(#4538)
1 parent af402d5 commit 5b36af0

File tree

7 files changed

+74
-7
lines changed

7 files changed

+74
-7
lines changed

opencti-platform/opencti-front/src/schema/relay.schema.graphql

+1
Original file line numberDiff line numberDiff line change
@@ -9883,6 +9883,7 @@ type CaseIncident implements BasicObject & StixObject & StixCoreObject & StixDom
98839883
severity: String
98849884
priority: String
98859885
authorized_members: [MemberAccess!]
9886+
currentUserAccessRight: String
98869887
}
98879888

98889889
enum CaseIncidentsOrdering {

opencti-platform/opencti-graphql/src/generated/graphql.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,7 @@ export type CaseIncident = BasicObject & Case & Container & StixCoreObject & Sti
20182018
createdBy?: Maybe<Identity>;
20192019
created_at: Scalars['DateTime']['output'];
20202020
creators?: Maybe<Array<Creator>>;
2021+
currentUserAccessRight?: Maybe<Scalars['String']['output']>;
20212022
description?: Maybe<Scalars['String']['output']>;
20222023
editContext?: Maybe<Array<EditUserContext>>;
20232024
entity_type: Scalars['String']['output'];
@@ -30981,6 +30982,7 @@ export type CaseIncidentResolvers<ContextType = any, ParentType extends Resolver
3098130982
createdBy?: Resolver<Maybe<ResolversTypes['Identity']>, ParentType, ContextType>;
3098230983
created_at?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
3098330984
creators?: Resolver<Maybe<Array<ResolversTypes['Creator']>>, ParentType, ContextType>;
30985+
currentUserAccessRight?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
3098430986
description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
3098530987
editContext?: Resolver<Maybe<Array<ResolversTypes['EditUserContext']>>, ParentType, ContextType>;
3098630988
entity_type?: Resolver<ResolversTypes['String'], ParentType, ContextType>;

opencti-platform/opencti-graphql/src/modules/case/case-incident/case-incident-domain.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { AuthContext, AuthUser } from '../../../types/user';
2-
import { createEntity, patchAttribute } from '../../../database/middleware';
2+
import { createEntity } from '../../../database/middleware';
33
import type { EntityOptions } from '../../../database/middleware-loader';
44
import { internalLoadById, listEntitiesPaginated, storeLoadById } from '../../../database/middleware-loader';
55
import { BUS_TOPICS } from '../../../config/conf';
6-
import { ABSTRACT_STIX_CORE_OBJECT, ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey } from '../../../schema/general';
6+
import { ABSTRACT_STIX_DOMAIN_OBJECT, buildRefRelationKey } from '../../../schema/general';
77
import { notify } from '../../../database/redis';
88
import { now } from '../../../utils/format';
99
import { userAddIndividual } from '../../../domain/user';
@@ -16,9 +16,7 @@ import type { CaseIncidentAddInput, MemberAccessInput } from '../../../generated
1616
import { isStixId } from '../../../schema/schemaUtils';
1717
import { RELATION_OBJECT } from '../../../schema/stixRefRelationship';
1818
import { FilterMode } from '../../../generated/graphql';
19-
import { isValidMemberAccessRight } from '../../../utils/access';
20-
import { containsValidAdmin } from '../../../utils/authorizedMembers';
21-
import { FunctionalError } from '../../../config/errors';
19+
import { editAuthorizedMembers } from '../../../utils/authorizedMembers';
2220

2321
export const findById: DomainFindById<BasicStoreEntityCaseIncident> = (context: AuthContext, user: AuthUser, caseIncidentId: string) => {
2422
return storeLoadById(context, user, caseIncidentId, ENTITY_TYPE_CONTAINER_CASE_INCIDENT);
@@ -63,7 +61,7 @@ export const caseIncidentContainsStixObjectOrStixRelationship = async (context:
6361
return caseIncidentFound.edges.length > 0;
6462
};
6563

66-
export const caseIncidentEditAuthorizedMembers = async (
64+
/* export const caseIncidentEditAuthorizedMembers = async (
6765
context: AuthContext,
6866
user: AuthUser,
6967
entityId: string,
@@ -92,4 +90,14 @@ export const caseIncidentEditAuthorizedMembers = async (
9290
const patch = { authorized_members };
9391
const { element } = await patchAttribute(context, user, entityId, ENTITY_TYPE_CONTAINER_CASE_INCIDENT, patch);
9492
return notify(BUS_TOPICS[ABSTRACT_STIX_CORE_OBJECT].EDIT_TOPIC, element, user);
93+
}; */
94+
95+
export const caseIncidentEditAuthorizedMembers = async (
96+
context: AuthContext,
97+
user: AuthUser,
98+
entityId: string,
99+
input: MemberAccessInput[] | undefined | null
100+
) => {
101+
const requiredCapabilities = ['KNOWLEDGE_KNUPDATE_KNMANAGEAUTHMEMBERS'];
102+
return editAuthorizedMembers(context, user, entityId, input, requiredCapabilities, ENTITY_TYPE_CONTAINER_CASE_INCIDENT);
95103
};

opencti-platform/opencti-graphql/src/modules/case/case-incident/case-incident-resolvers.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { RELATION_OBJECT_ASSIGNEE } from '../../../schema/stixRefRelationship';
44
import { stixDomainObjectDelete } from '../../../domain/stixDomainObject';
55
import { addCaseIncident, caseIncidentContainsStixObjectOrStixRelationship, findAll, findById, caseIncidentEditAuthorizedMembers } from './case-incident-domain';
66
import { getAuthorizedMembers } from '../../../utils/authorizedMembers';
7+
import { getUserAccessRight } from '../../../utils/access';
78

89
const caseIncidentResolvers: Resolvers = {
910
Query: {
@@ -15,6 +16,7 @@ const caseIncidentResolvers: Resolvers = {
1516
},
1617
CaseIncident: {
1718
authorized_members: (caseIncidentResponse, _, context) => getAuthorizedMembers(context, context.user, caseIncidentResponse),
19+
currentUserAccessRight: (caseIncidentResponse, _, context) => getUserAccessRight(context.user, caseIncidentResponse),
1820
},
1921
CaseIncidentsOrdering: {
2022
creator: 'creator_id',

opencti-platform/opencti-graphql/src/modules/case/case-incident/case-incident.graphql

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ type CaseIncident implements BasicObject & StixObject & StixCoreObject & StixDom
138138
severity: String
139139
priority: String
140140
authorized_members: [MemberAccess!]
141+
currentUserAccessRight: String
141142
}
142143

143144
# Ordering

opencti-platform/opencti-graphql/src/utils/authorizedMembers.ts

+42-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { uniq } from 'ramda';
22
import { isEmptyField } from '../database/utils';
33
import type { AuthContext, AuthUser } from '../types/user';
44
import type { BasicGroupEntity, BasicStoreEntity } from '../types/store';
5-
import type { MemberAccess } from '../generated/graphql';
5+
import type { MemberAccess, MemberAccessInput } from '../generated/graphql';
66
import {
77
type AuthorizedMember,
88
isUserHasCapabilities,
9+
isValidMemberAccessRight,
910
MEMBER_ACCESS_ALL,
1011
MEMBER_ACCESS_CREATOR,
1112
MEMBER_ACCESS_RIGHT_ADMIN,
@@ -16,6 +17,12 @@ import { findAllMembers, findById as findUser } from '../domain/user';
1617
import { findById as findGroup } from '../domain/group';
1718
import { findById as findOrganization } from '../modules/organization/organization-domain';
1819
import { RELATION_MEMBER_OF, RELATION_PARTICIPATE_TO } from '../schema/internalRelationship';
20+
import { FunctionalError } from '../config/errors';
21+
import { patchAttribute } from '../database/middleware';
22+
import { ENTITY_TYPE_CONTAINER_FEEDBACK } from '../modules/case/feedback/feedback-types';
23+
import { notify } from '../database/redis';
24+
import { BUS_TOPICS } from '../config/conf';
25+
import { ABSTRACT_STIX_CORE_OBJECT } from '../schema/general';
1926

2027
export const getAuthorizedMembers = async (
2128
context: AuthContext,
@@ -80,3 +87,37 @@ export const containsValidAdmin = async (
8087
// at least 1 user with admin access and admin exploration capability
8188
return authorizedUsers.length > 0;
8289
};
90+
91+
export const editAuthorizedMembers = async (
92+
context: AuthContext,
93+
user: AuthUser,
94+
entityId: string,
95+
input: MemberAccessInput[] | undefined | null,
96+
requiredCapabilities: string[],
97+
entityType: string,
98+
) => {
99+
let authorized_members: { id: string, access_right: string }[] | null = null;
100+
101+
if (input) {
102+
// validate input (validate access right) and remove duplicates
103+
const filteredInput = input.filter((value, index, array) => {
104+
return isValidMemberAccessRight(value.access_right) && array.findIndex((e) => e.id === value.id) === index;
105+
});
106+
107+
const hasValidAdmin = await containsValidAdmin(
108+
context,
109+
filteredInput,
110+
requiredCapabilities,
111+
);
112+
if (!hasValidAdmin) {
113+
throw FunctionalError('It should have at least one valid member with admin access');
114+
}
115+
116+
authorized_members = filteredInput.map(({ id, access_right }) => ({ id, access_right }));
117+
}
118+
119+
const patch = { authorized_members };
120+
const { element } = await patchAttribute(context, user, entityId, entityType, patch);
121+
// TODO FIX type error
122+
return notify(BUS_TOPICS[entityType].EDIT_TOPIC, element, user);
123+
};

opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/case-incident-response-test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ const READ_QUERY = gql`
2929
toStix
3030
authorized_members {
3131
id
32+
access_right
3233
}
34+
currentUserAccessRight
3335
}
3436
}
3537
`;
@@ -186,6 +188,16 @@ describe('Case Incident Response standard behavior with authorized_members activ
186188
}
187189
]);
188190
});
191+
it('should Case Incident Response get current User access right', async () => {
192+
// Get current User access right
193+
const currentUserAccessRightQueryResult = await queryAsAdmin({
194+
query: READ_QUERY,
195+
variables: { id: caseIncidentResponse.id },
196+
});
197+
198+
expect(currentUserAccessRightQueryResult).not.toBeNull();
199+
expect(currentUserAccessRightQueryResult?.data?.caseIncident.currentUserAccessRight).toEqual('admin');
200+
});
189201
it('should Case Incident Response deleted', async () => {
190202
// Delete the case
191203
await queryAsAdmin({

0 commit comments

Comments
 (0)