diff --git a/docs/changelog.md b/docs/changelog.md index ec207b074f..7cf85eeb98 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -168,6 +168,7 @@ See documentation, to learn more about using new API. - Intro for documentation - Quick start section for developers in docs - Quick start section for users in docs +- Documentation for user permissions - Allow multiple extension directories for sc-memory - CD for publishing sc-machine binaries as archive on Github - CI for checking sc-machine tests build with Conan dependencies diff --git a/docs/index.md b/docs/index.md index 696a4891ad..afd140cc6f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,8 @@ Table of contents: * [C++ Core API](sc-memory/api/cpp/core/api.md) - *documentation of C++ core API for creating, retrieving and erasing sc-elements in sc-memory* * C++ Extended API - *documentation of C++ extended API for manipulating with system identifiers of sc-elements and sc-templates* * [C++ System Identifier API](sc-memory/api/cpp/extended/helper_api.md) - *documentation of C++ extended API for manipulating with system identifiers of sc-elements* - * [C++ ScTemplate API](sc-memory/api/cpp/extended/template_api.md) - *documentation of C++ extended API for creating and retrieving graphs (it is very useful when you want to work big sc-constructions)* + * [C++ ScTemplate API](sc-memory/api/cpp/extended/template_api.md) - *documentation of C++ extended API for creating and retrieving graphs (it is very useful when you want to work big sc-constructions)* + * [C++ User Permissions API](sc-memory/api/cpp/extended/permissions_api.md) - *documentation of handling users and their permissions in knowledge base* * C++ Agents API - *documentation of C++ Agents API for creating agents* * [C++ Events API](sc-memory/api/cpp/extended/agents/events.md) - *enables developers to create and manage events within the sc-machine, allowing agents to respond dynamically to various triggers* * [C++ Event Subscriptions API](sc-memory/api/cpp/extended/agents/event_subscriptions.md) - *details how agents can subscribe to specific events and receive notifications when those events occur* diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/erase_local_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/erase_local_read_permissions_for_user.gwf new file mode 100644 index 0000000000..08bf9e4072 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/erase_local_read_permissions_for_user.gwf @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/generate_local_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/generate_local_read_permissions_for_user.gwf new file mode 100644 index 0000000000..f212659337 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/generate_local_read_permissions_for_user.gwf @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_user.gwf new file mode 100644 index 0000000000..446277de12 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_user.gwf @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_users_set.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_users_set.gwf new file mode 100644 index 0000000000..d3a87550b9 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/global_read_permissions_for_users_set.gwf @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_user.gwf new file mode 100644 index 0000000000..d2e364d6a8 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_user.gwf @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_users_set.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_users_set.gwf new file mode 100644 index 0000000000..c268ee12bc --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/local_read_permissions_for_users_set.gwf @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_user.gwf new file mode 100644 index 0000000000..e24a5ec2f8 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_user.gwf @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_users_set.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_users_set.gwf new file mode 100644 index 0000000000..4231219274 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/no_global_read_permissions_for_users_set.gwf @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_user.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_user.gwf new file mode 100644 index 0000000000..631e56c04d --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_user.gwf @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_users_set.gwf b/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_users_set.gwf new file mode 100644 index 0000000000..02715d3272 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/images/permissions/no_local_read_permissions_for_users_set.gwf @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sc-memory/api/cpp/extended/permissions_api.md b/docs/sc-memory/api/cpp/extended/permissions_api.md new file mode 100644 index 0000000000..c2f5502101 --- /dev/null +++ b/docs/sc-memory/api/cpp/extended/permissions_api.md @@ -0,0 +1,866 @@ +# **User permissions API** + +!!! note + This documentation is correct for only versions of sc-machine that >= 0.10.0. +--- + +This API allows to handle users and their permissions in knowledge base. + +## **Who are users of ostis-systems?** + +Users interact with ostis-systems. Users can be other systems, agents or people. All users of an ostis-system can perform actions on its knowledge base. There are six classes of user actions in knowledge base: + +* action_read_from_sc_memory; +* action_generate_in_sc_memory; +* action_erase_from_sc_memory; +* action_read_permissions_from_sc_memory; +* action_generate_permissions_in_sc_memory; +* action_erase_permissions_from_sc_memory. + +Before a user action is performed, it is checked whether the user has permissions to perform actions of the specified class. + +By default, user permissions are not handled by sc-machine. This is configured via the sc-machine config (`.ini`). To enable user permissions handling in the sc-machine, go to the group `[sc-memory]` and set `user_mode` as `true`. + +```ini +[sc-memory] +... +user_mode = true +... +``` + +## **How are users managed?** + +You can only work with sc-memory through methods provided in `ScMemoryContext` class. Each object of this class can be considered as an object that handles information about a user (including his permissions) when that user invokes methods through that object. + +To work with sc-memory, you should create object of `ScMemoryContext` class or use existing one. If you create context via constructor, then this context will have guest user (user with `concept_guest_user` class). + +```cpp +ScMemoryContext context; +ScAddr const & guestUserAddr = context.GetUser(); +// This user should belongs `concept_guest_user` class. + +// After you can use `context` to generate, search or erase sc-elements +// in sc-memory. +``` + +You can get user from object of context, if you need to handle this user. + +```cpp +ScAddr const & userAddr = context.GetUser(); +``` + +`concept_guest_user` class is default class for all users in sc-memory. By default, all guest users haven't permissions. You can specify permissions for their class. See documentation below to learn how to do it. + +When some user initiates a sc-event, an object of `ScMemoryContext` with this user is created for the agent that reacted to this sc-event. After this agent uses this context to manipulate with sc-constructions within sc-memory. Each agent class has `m_context` field. You should use it to call methods in sc-memory. + +## **How does the sc-machine identifies users?** + +You can identify user. User identification refers to the process of identifying a user on ostis-system, i.e., that the specified guest user is some user that is on the knowledge base. + +It is useful when your ostis-system implements functionality to work with guest users. The sc-machine provides users identification. You can identify some guest user as user that had been already registered in the system. Users identification allows you to implement your own agent to register/authorize users by password, token or something else. + +To identify user in the sc-memory, you should create connection between guest user and identified user. + +```scs +..some_guest_user => nrel_identified_user: ..some_user;; +``` + +After that, all contexts that had specified guest user will have specified identified user. + +To unidentify identified user, you can create reverse connection between specified guest user and specified identified user. + +## **How does the sc-machine authenticate users?** + +Users can be known in advance and then guest users and their identification is unnecessary, but all users should be authenticated in sc-memory. User authentication involves the process of verifying the authenticity of identified user and storing information about that user in sc-memory. + +To authenticate user in sc-memory, you should create connection between `concept_authentication_request` and user: + +```scs +concept_authentication_request -> ..some_user;; +``` + +You should do it once, no more. After the sc-machine authenticates this user, it means that connection between `concept_authenticated_user` and user has been created and all contexts with this user have been authenticated. + +```scs +concept_authenticated_user ~> ..some_user;; +``` + +If you remove this sc-arc between `concept_authenticated_user` and the user, then the user and all contexts with user will be also unauthenticated. + +## **Examples of using user identification and authentication** + +### **Example of user identification** + +You should identify guest user as user that should be authenticated. + +```cpp +// Create context with guest user. +ScMemoryContext context; +// Get guest user from created context. +ScAddr const & guestUserAddr = context.GetUser(); + +// Find a user, which should be identified. You can provide your own logic +// of user identification before. +ScAddr const & userAddr1 = context.SearchElementBySystemIdentifier("user_1"); + +// Before user identification, specify that user isn't identified. +// This way, you can subscribe to sc-event of erasing negative sc-arc, +// because when you identify user, all existing negative sc-arcs +// between `nrel_identified_user` and sc-arc between guest user and user +// to be identified are erased. This logic will help you to wait for user +// to be identified. +ScAddr const & arcAddr = ScMemory::ms_globalContext->GenerateConnector( + ScType::ConstCommonArc, guestUserAddr, userAddr1); +ScMemory::ms_globalContext->GenerateConnector( + ScType::ConstTempNegArc, ScKeynodes::nrel_identified_user, arcAddr); + +// Create sc-event waiter to wait user to be identified. +// You should subscribe to sc-event of erasing negative sc-arc incoming to +// sc-arc between guest user and user to be identified. +auto eventWaiter + = ScMemory::ms_globalContext->CreateConditionWaiter< + ScEventBeforeEraseIncomingArc>( + arcAddr, + [&]() -> void + { + // Identify guest user. + ScMemory::ms_globalContext->GenerateConnector( + ScType::ConstTempPosArc, ScKeynodes::nrel_identified_user, arcAddr); + // Only `ScMemory::ms_globalContext` can identify users. + }, + [&](ScEventBeforeEraseIncomingArc const & event) + -> bool + { + // Check that sc-arc from `nrel_identified_user` is erased. + return event.GetArcSourceElement() + == ScKeynodes::nrel_identified_user; + }); + +// After creation, call method `Wait` and specify time while you +// will wait sc-event for specified subscription sc-element. +eventWaiter->Wait(200); // milliseconds +// By default, this wait time equals to 5000 milliseconds. +// You will wait until sc-event occurs or until specified time expires. +``` + +After, you can authenticate identified user. + +### **Example of user authentication** + +To do this programly you can create waiter to wait sc-event of adding outgoing sc-arc from `concept_authenticated_user` and request user to be authenticated, i.e. create sc-arc between `concept_authentication_request` and user. After waiting this sc-event, your user will be authenticated. + +```cpp +... +// Find a user, which you want to authenticate. +ScAddr const & userAddr1 = context.SearchElementBySystemIdentifier("user_1"); + +// Before user authentication, specify that user isn't authenticated. +// This way, you can subscribe to sc-event of erasing negative sc-arc, +// because when you authenticate user, all existing negative sc-arcs +// between `concept_authenticated_user` and user are erased. This logic will +// help you to wait for user to be authenticated. +ScMemory::ms_globalContext->GenerateConnector( + ScType::ConstTempNegArc, + ScKeynodes::concept_authenticated_user, + userAddr1); + +// Create sc-event waiter to wait user to be authenticated. +// You should subscribe to sc-event of erasing negative sc-arc incoming to +// user. +auto eventWaiter + = ScMemory::ms_globalContext->CreateConditionWaiter< + ScEventBeforeEraseIncomingArc>( + userAddr1, + [&]() -> void + { + ScMemory::ms_globalContext->GenerateConnector( + ScType::ConstPermPosArc, + ScKeynodes::concept_authentication_request, + userAddr1); + + // Only `ScMemory::ms_globalContext` can authenticate users. + }, + [&](ScEventBeforeEraseIncomingArc const & event) + -> bool + { + // Check that sc-arc from `concept_authenticated_user` is erased. + return event.GetArcSourceElement() + == ScKeynodes::concept_authenticated_user; + }); + +// After creation, call method `Wait` and specify time while you +// will wait sc-event for specified subscription sc-element. +eventWaiter->Wait(200); // milliseconds +// By default, this wait time equals to 5000 milliseconds. +// You will wait until sc-event occurs or until specified time expires. +``` + +Yes, this way of waiting for user authentication is complicated, but it ensures that the NOT factors in the user information are accounted for. In the future, transaction mechanisms will be implemented in the sc-machine to simplify its API. + +### **Example of user unauthentication** + +To unauthenticate user, you must erase sc-arc between `concept_authenticated_user` and user. + +```cpp +... +// Find a user, which you want to unauthenticate. +ScAddr const & userAddr1 = context.SearchElementBySystemIdentifier("user_1"); + +// Create sc-event waiter to wait user to be unauthenticated. +// You should subscribe to sc-event of adding negative sc-arc incoming to +// user, because it will be added when you erase sc-arcs between +// `concept_authenticated_user` and user. +auto eventWaiter + = ScMemory::ms_globalContext->CreateConditionWaiter< + ScEventAfterGenerateIncomingArc>( + userAddr1, + [&]() -> void + { + // Find and erase connection between `concept_authenticated_user` + // and user. + ScIterator3Ptr it3 = ScMemory::ms_globalContext->Iterator3( + ScKeynodes::concept_authenticated_user, + ScType::EdgeAccessConstPosTemp, + userAddr1 + ); + if (it3->Next()) + { + ScMemory::ms_globalContext->EraseElement(it3->Get(1)); + } + + // Only `ScMemory::ms_globalContext` can unauthenticate users. + }, + [&](ScEventAfterGenerateIncomingArc const & event) + -> bool + { + // Check that sc-arc from `concept_authenticated_user` is added. + return event.GetArcSourceElement() + == ScKeynodes::concept_authenticated_user; + }); + +// After creation, call method `Wait` and specify time while you +// will wait sc-event for specified subscription sc-element. +eventWaiter->Wait(200); // milliseconds +``` + +You can use these examples to identify guest users. + +## **How are user permissions managed?** + +### **Action classes used to handle user permissions** + +In order for a user to successfully execute a method from `ScMemoryContext`, it is necessary that the knowledge base for that user specifies that it can perform the class of actions that corresponds to that method. + +Description of action classes that users of ostis-system can perform in its knowledge base is represented below: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Action classSystem identifier of action class sc-nodeAbbreviationLogic if user has permissions to execute actions of the specified class
reading from sc-memory actionaction_read_from_sc_memoryRThe user can execute all methods that read sc-constructions from knowledge base.
generating in sc-memory actionaction_generate_in_sc_memoryGThe user can execute all methods that generate sc-constructions in knowledge base.
erasing from sc-memory actionaction_erase_from_sc_memoryEThe user can execute all methods that erase sc-constructions from knowledge base.
reading permissions from sc-memory actionaction_read_permissions_from_sc_memoryRPThe user can read permissions of other users from knowledge base.
generating permissions in sc-memory actionaction_generate_permissions_in_sc_memoryGPThe user can generate permissions for other users in knowledge base.
erasing permissions from sc-memory actionaction_erase_permissions_from_sc_memoryEPThe user can erase permissions of other users from knowledge base.
+ +Each core method of [**C++ Core API**](../core/api.md) checks user permissions. All methods of *C++ Extended API* use methods of *C++ Core API*. Description of ScMemoryContext API methods and user permissions required to execute these methods is represented below: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ScMemoryContext API methodRGELogic if user hasn't required permissions to perform method
GenerateNode, GenerateLink---These methods don't require any permissions for users.
GenerateConnector-+-If user hasn't permissions to add sc-connector from specified source sc-element or to specified target sc-element, then method will throw utils::ExceptionInvalidState.
IsElement+--If user hasn't permissions to read specified sc-element, then method will throw utils::ExceptionInvalidState.
GetElementType+--If user hasn't permissions to read specified sc-element, then method will throw utils::ExceptionInvalidState.
SetElementSubtype-+-If user hasn't permissions to update specified sc-element sc-type, then method will throw utils::ExceptionInvalidState.
GetConnectorIncidentElements, GetArcSourceElement, GetArcTargetElement+--If user hasn't permissions to read specified sc-connector or its incident sc-elements, then method will throw utils::ExceptionInvalidState.
CreateIterator3, CreateIterator5, ForEach, ForEach+--If user hasn't permissions to read some sc-connectors from or to specified sc-element, then method won't return these sc-connectors to user: method ScIterator::Next will skip these sc-connectors. If user has permissions to read sc-connector from or to specified sc-element, but he hasn't permissions to read other incident sc-elements, then method ScIterator::Get will throw utils::ExceptionInvalidState if user tries to get such permitted sc-element by index in found sc-construction. Methods ForEach will return empty sc-address in such case.
EraseElement--+If user hasn't permissions to erase specified sc-element, then method will return false.
SetLinkContent-++If user hasn't permissions to change (erase and write) content for specified sc-link, then method will throw utils::ExceptionInvalidState.
GetLinkContent+--If user hasn't permissions to read specified sc-link by specified content, then method will throw utils::ExceptionInvalidState.
SearchLinksByContent, SearchLinksByContentSubstring+--If user hasn't permissions to read some sc-links that have specified content, then method won't return these sc-links.
+ +### **Global and local user permissions** + +Depending on where the user can perform actions in the knowledge base, their permissions are divided into global and local permissions: + +* global permissions is permissions over entire knowledge base; +* local permissions is permissions in some part (sc-structure) of knowledge base. + +Permissions can be set on a specific user or group (set or class) of users. + +All permissions can be represented as connections between users, action classes and sc-structures: + + + + + + + + + + + + + + + + + + + + + +
Permissions classSystem identifier of relation sc-node for concrete userDescription
Global permissionsnrel_user_action_classBinary relation between concrete user and action class
Local permissionsnrel_user_action_class_within_sc_structureTernary relation between concrete user and action class with sc-structure where actions of specified class can be performed by this user
+ + + + + + + + + + + + + + + + + + + + + +
Permissions classSystem identifier of relation sc-node for users setDescription
Global permissionsnrel_users_set_action_classBinary relation between users set and action class
Local permissionsnrel_users_set_action_class_within_sc_structureTernary relation between users set and action class with sc-structure where actions of specified class can be performed by this one of users
+ +Examples of global and local read permissions for user and users set: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PermissionsSCg-code exampleSCs-code example
User has global read permissions +
+        
+..user <~ concept_user;;
+
+nrel_user_action_class
+~> (..user => action_read_from_sc_memory);; 
+        
+      
+
User has local read permissions +
+        
+..user <~ concept_user;;
+
+..structure = [*
+    concept_set ~> ..set;;
+*];;
+
+nrel_user_action_class_within_sc_structure
+~> (..user => (action_read_from_sc_memory => ..structure));;
+        
+      
+
Each user in users set has global read permissions +
+        
+nrel_users_set_action_class
+~> (concept_user => action_read_from_sc_memory);;
+        
+      
+
Each user in users set has local read permissions +
+        
+..structure = [*
+    concept_set ~> ..set;;
+*];;
+
+nrel_users_set_action_class_within_sc_structure
+~> (..user => (action_read_from_sc_memory => ..structure));;
+        
+      
+
User hasn't global read permissions +
+        
+..user <~ concept_user;;
+
+nrel_user_action_class
+~|> (..user => action_read_from_sc_memory);;
+        
+      
+
User hasn't local read permissions +
+        
+..user <~ concept_user;;
+
+..structure = [*
+concept_set ~> ..set;;
+*];;
+
+nrel_user_action_class_within_sc_structure
+~|> (..user => (action_read_from_sc_memory => ..structure));;
+        
+      
+
Each user in users set hasn't global read permissions +
+        
+nrel_users_set_action_class
+~|> (concept_user => action_read_from_sc_memory);;
+        
+      
+
Each user in users set hasn't local read permissions +
+        
+..structure = [*
+    concept_set ~> ..set;;
+*];;
+
+nrel_users_set_action_class_within_sc_structure
+~|> (..user => (action_read_from_sc_memory => ..structure));;
+        
+      
+
+ +In these examples, you can use any other action class (`action_generate_in_sc_memory`, `action_erase_from_sc_memory`, `action_read_permissions_from_sc_memory`, `action_generate_permissions_in_sc_memory` or `action_erase_permissions_from_sc_memory`) instead of `action_read_from_sc_memory`. + +All sc-arcs from permissions classes (relations) must be permanent or temporary. All sc-arcs from user groups (classes or sets) must be permanent or temporary. + +!!! note + If the knowledge base does not explicitly specify permissions for a user, it is equivalent to saying that this user does not have them. + +!!! note + In order to erase permissions for a user it is enough to erase an membership sc-arc from the relation that indicated permissions. + +!!! note + In the sc-machine there is a global system context -- `ScMemory::ms_globalContext`, that has all permissions. You can use it to update permissions that can be used to read, update or erase permissions for other users. + +!!! warning + Erasing a positive membership sc-arc between relation and sc-arc between the user and an action class, that the user can perform (pair with sc-structure and action class), automatically creates a negative membership sc-arc between the given relation and the sc-arc between the user and the action class (the pair with sc-structure and action class). + + + +!!! warning + Creating a positive membership sc-arc between relation and sc-arc between the user and an action class, that the user can perform (pair with sc-structure and action class), automatically erases all negative membership sc-arcs between the given relation and the sc-arc between the user and the action class (the pair with sc-structure and action class). + + + +--- + +### **Compatibility of global and local user permissions** + +Both global and local permissions can be described for the same user. It is important to know the logic of how they work together. For example, concrete user wants to handle some sc-construction. There may be several cases: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CaseCriterion 1. Does specified sc-construction belong to any permitted sc-structure?Criterion 2. Does user have global permissions?Criterion 3. Does user have local permissions?Result. Can user handle the specified sc-construction?
1No, it doesn't.No, he doesn't.No, he doesn't.No, he doesn't.
2No, it doesn't.Yes. He has global write permissions.No, he doesn't.Yes. He can only add sc-elements into the specified sc-construction, because he has global write permissions.
3Yes. The sc-construction is in a sc-structure that indicates that certain permissions are required. Some users have permissions to this sc-structure.No, he doesn't.No, he doesn't.No, he doesn't.
4Yes. The sc-construction is in a sc-structure that indicates that certain permissions are required. Some users have permissions to this sc-structure.Yes. He has global read permissions.No, he doesn't.No, he doesn't. The user hasn't local permissions for the specified sc-structure. But he can read any sc-constructions in knowledge base, which doesn't have permitted sc-structures.
5Yes. The sc-construction is in a sc-structure that indicates that certain permissions are required. Some users have permissions to this sc-structure.No, he doesn't.Yes. He has local write permissions for the specified sc-structure.Yes. The user can only add sc-elements into the specified sc-structure. But he can't handle any sc-constructions in knowledge base other than the given one.
6Yes. The sc-construction is in a sc-structure that indicates that certain permissions are required. Some users have permissions to this sc-structure.Yes. He has global write permissions.Yes. He has local write permissions for the specified sc-structure.Yes. The user can add sc-elements into the specified sc-structure. And he can add sc-element into any sc-constructions in knowledge base other than the given one.
+ +--- + +### **Examples of using user permissions** + +If you want to update permissions for a user, then you can describe them in the knowledge base in any format convenient for you (SCs-code or SCg-code) or do it programly. + +#### **Example for adding (updating) user permissions** + +If you want to add permissions for user constantly, specify permissions for this user in the knowledge base. See examples of local and global user permissions above. + +To do this programly you can create waiter to wait sc-event of adding outgoing sc-arc from permissions class and add permissions for this user. After waiting this sc-event, your user will have new user permissions. + +```cpp +... +// Find a user, for whom you need to add new permissions. +ScAddr const & userAddr1 = context.SearchElementBySystemIdentifier("user_1"); +// Find a structure, within which the user should have permissions. +ScAddr const & structureAddr + = context.SearchElementBySystemIdentifier("my_structure"); + +// Before adding new user permissions, specify that user doesn't have these +// permissions. This way, you can subscribe to sc-event of erasing negative +// sc-arc, because when you add new permissions for user, all existing +// negative sc-arcs to permissions are erased. This logic will help you to +// wait for user's permissions to be changed. +ScAddr const & _actionClassArcAddr = context.GenerateConnector( + ScType::ConstCommonArc, + ScKeynodes::action_generate_in_sc_memory, + structureAddr); +ScAddr const & _userArcAddr = context.GenerateConnector( + ScType::ConstCommonArc, + userAddr1, + _actionClassArcAddr); +context.GenerateConnector( + ScType::ConstTempNegArc, + ScKeynodes::nrel_user_action_class_within_sc_structure, + _userArcAddr); + +// Create sc-event waiter to wait adding new permissions for specified user. +// You should subscribe to sc-event of erasing negative sc-arc. +// Negative sc-arc is erased when you added new permissions for user. +auto eventWaiter + = context.CreateConditionWaiter< + ScEventEraseOutgoingArc>( + ScKeynodes::nrel_user_action_class_within_sc_structure, + [&]() -> void + { + // Update user permissions here. + ScAddr const & actionClassArcAddr = context.GenerateConnector( + ScType::ConstCommonArc, + ScKeynodes::action_generate_in_sc_memory, + structureAddr); + ScAddr const & userArcAddr = context.GenerateConnector( + ScType::ConstCommonArc, + userAddr1, + actionClassArcAddr); + context.GenerateConnector( + ScType::EdgeAccessConstPosTemp, + ScKeynodes::nrel_user_action_class_within_sc_structure, + userArcAddr); + // You should create sc-arc from permissions class at + // the end of this callback. + + // And note, that if `context` user doesn't have permissions to create + // permissions in sc-memory for other users, you should to update + // permissions for user of `context` or use `ScMemory::ms_globalContext` + // that has all permissions, by default. + }, + [&](ScEventEraseOutgoingArc const & event) + -> bool + { + // Check that permissions for specified are updated. + ScAddr targetElementAddr = event.GetArcTargetElement(); + if (context.GetElementType(targetElementAddr) + != ScType::ConstCommonArc) + return false; + + auto [userAddr, permissionsAddr] + = context.GetConnectorIncidentElements(targetElementAddr); + + return userAddr == userAddr1; + }); + +// After creation, call method `Wait` and specify time while you +// will wait sc-event for specified subscription sc-element. +eventWaiter->Wait(200); // milliseconds +// By default, this wait time equals to 5000 milliseconds. +// You will wait until sc-event occurs or until specified time expires. +``` + +Yes, this way of waiting for permissions to change is complicated, but it ensures that the NOT factors in the user information are accounted for. In the future, transaction mechanisms will be implemented in the sc-machine to simplify its API. + +#### **Example for erasing user permissions** + +To erase permissions for a user, you must erase sc-arc from permissions class. + +```cpp +... +// Find a user, for whom you need to erase permissions. +ScAddr const & userAddr1 = context.SearchElementBySystemIdentifier("user_1"); +// Find a structure, within which the user should no longer have rights +ScAddr const & structureAddr + = context.SearchElementBySystemIdentifier("my_structure"); +// Create sc-event waiter to wait erasing permissions for specified user. +// You should subscribe to sc-event of adding negative sc-arc. +// Negative sc-arc is added when you erases user permissions. +auto eventWaiter + = context.CreateConditionWaiter< + ScEventAfterGenerateOutgoingArc>( + ScKeynodes::nrel_user_action_class_within_sc_structure, + [&]() -> void + { + // Update user permissions here. + ScTemplate permissionsTemplate; + permissionsTemplate.Triple( + ScKeynodes::action_generate_in_sc_memory, + ScType::VarCommonArc >> "_action_class_arc", + structureAddr + ); + permissionsTemplate.Quintuple( + userAddr1, + ScType::VarCommonArc, + "_action_class_arc", + ScType::VarTempPosArc >> "_permissions_arc", + ScKeynodes::nrel_user_action_class_within_sc_structure + ); + ScTemplateSearchResult result; + if (context.SearchByTemplate(permissionsTemplate, result)) + { + context.EraseElement(result[0]["_permissions_arc"]); + // You should erase sc-arc from permissions class at + // the end of this callback. + } + + // And note, that if `context` user doesn't have permissions to read + // permissions in sc-memory for other users, you should to update + // permissions for user of `context` or use `ScMemory::ms_globalContext` + // that has all permissions, by default. + }, + [&](ScEventAfterGenerateOutgoingArc const & event) + -> bool + { + // Check that permissions for specified are erased. + ScAddr targetElementAddr = event.GetArcTargetElement(); + if (context.GetElementType(targetElementAddr) + != ScType::ConstCommonArc) + return false; + + auto [userAddr, permissionsAddr] + = context.GetConnectorIncidentElements(targetElementAddr); + + return userAddr == userAddr1; + }); + +// After creation, call method `Wait` and specify time while you +// will wait sc-event for specified subscription sc-element. +eventWaiter->Wait(200); // milliseconds +``` + +These examples can be reused for any of permissions classes described above. + +--- + +## **Frequently Asked Questions** + +- [How to specify role for users in knowledge base and set permissions for this role?](#how-to-specify-role-for-users-in-knowledge-base-and-set-permissions-for-this-role) +- [How to specify permissions to structures that are not described in knowledge base sources?](#how-to-specify-permissions-to-structures-that-are-not-described-in-knowledge-base-sources) + +### **How to specify role for users in knowledge base and set permissions for this role?** + +A role for users should be understood as a class of users. You can specify permission for user classes. + +The following example shows how global and local permissions are specified for a class of users: + +```scs +concept_users_class_1 +~> ..user_1;; + +nrel_users_set_action_class +~> (concept_users_class_1 => action_read_from_sc_memory);; + +nrel_users_set_action_class_within_sc_structure +~> (concept_users_class_1 => (action_read_from_sc_memory => ..structure));; + +..structure = [* + concept_users_class_2 ~> ..user_2;; + ..user_2 -> rrel_password: [password];; +*];; +``` + +This example shows that all users from `concept_users_class_1` can view the entire knowledge base besides the structure describing users from `concept_users_class_2`. + +### **How to specify permissions to structures that are not described in knowledge base sources?** + +You can generate and update structures in knowledge base while system is running. You can also generate and modify permissions to structures in knowledge base while system is running. To do this, you should use all available API methods. diff --git a/mkdocs.yml b/mkdocs.yml index 7ab6af3c6b..6422a2082e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,6 +20,7 @@ nav: - C++ Extended API: - C++ System Identifier API: sc-memory/api/cpp/extended/helper_api.md - C++ ScTemplate API: sc-memory/api/cpp/extended/template_api.md + - C++ User Permissions API: sc-memory/api/cpp/extended/permissions_api.md - C++ Agents API: - C++ Events API: sc-memory/api/cpp/extended/agents/events.md - C++ Event Subscriptions API: sc-memory/api/cpp/extended/agents/event_subscriptions.md diff --git a/sc-memory/sc-core/src/sc_memory_context_permissions.c b/sc-memory/sc-core/src/sc_memory_context_permissions.c index 15370e9ace..58d48a1d9e 100644 --- a/sc-memory/sc-core/src/sc_memory_context_permissions.c +++ b/sc-memory/sc-core/src/sc_memory_context_permissions.c @@ -263,6 +263,16 @@ sc_result _sc_memory_context_manager_on_identified_user( sc_monitor_release_write(&ctx->monitor); + // Remove all negative sc-arcs + sc_iterator3 * it3 = sc_iterator3_f_a_f_new( + s_memory_default_ctx, + manager->nrel_identified_user_addr, + sc_type_const_temp_neg_arc, + arc_to_identified_user_addr); + while (sc_iterator3_next(it3)) + sc_memory_element_free(s_memory_default_ctx, sc_iterator3_value(it3, 1)); + sc_iterator3_free(it3); + return SC_RESULT_OK; } @@ -297,6 +307,10 @@ sc_result _sc_memory_context_manager_on_authentication_request_user( sc_memory_element_free(s_memory_default_ctx, connector_addr); + sc_addr const auth_arc_addr = sc_memory_arc_new( + s_memory_default_ctx, sc_type_const_temp_pos_arc, manager->concept_authenticated_user_addr, user_addr); + _sc_context_set_permissions_for_element(auth_arc_addr, SC_CONTEXT_PERMISSIONS_TO_ALL_PERMISSIONS); + // Remove all negative sc-arcs sc_iterator3 * it3 = sc_iterator3_f_a_f_new( s_memory_default_ctx, manager->concept_authenticated_user_addr, sc_type_const_temp_neg_arc, user_addr); @@ -304,10 +318,6 @@ sc_result _sc_memory_context_manager_on_authentication_request_user( sc_memory_element_free(s_memory_default_ctx, sc_iterator3_value(it3, 1)); sc_iterator3_free(it3); - sc_addr const auth_arc_addr = sc_memory_arc_new( - s_memory_default_ctx, sc_type_const_temp_pos_arc, manager->concept_authenticated_user_addr, user_addr); - _sc_context_set_permissions_for_element(auth_arc_addr, SC_CONTEXT_PERMISSIONS_TO_ALL_PERMISSIONS); - return SC_RESULT_OK; } diff --git a/sc-memory/sc-memory/include/sc-memory/sc_keynodes.hpp b/sc-memory/sc-memory/include/sc-memory/sc_keynodes.hpp index dfc7e8e011..78d5ce61fa 100644 --- a/sc-memory/sc-memory/include/sc-memory/sc_keynodes.hpp +++ b/sc-memory/sc-memory/include/sc-memory/sc_keynodes.hpp @@ -298,6 +298,43 @@ class _SC_EXTERN ScKeynodes : public ScObject "sc_event_before_change_link_content", ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const concept_guest_user{"concept_guest_user", ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const nrel_identified_user{"nrel_identified_user", ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const concept_authentication_request_user{ + "concept_authentication_request_user", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const concept_authenticated_user{ + "concept_authenticated_user", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const nrel_user_action_class{"nrel_user_action_class", ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const nrel_users_set_action_class{ + "nrel_users_set_action_class", + ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const nrel_user_action_class_within_sc_structure{ + "nrel_user_action_class_within_sc_structure", + ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const nrel_users_set_action_class_within_sc_structure{ + "nrel_users_set_action_class_within_sc_structure", + ScType::ConstNodeNonRole}; + _SC_EXTERN static inline ScKeynode const action_read_from_sc_memory{ + "action_read_from_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const action_generate_in_sc_memory{ + "action_generate_in_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const action_erase_from_sc_memory{ + "action_erase_from_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const action_read_permissions_from_sc_memory{ + "action_read_permissions_from_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const action_generate_permissions_in_sc_memory{ + "action_generate_permissions_in_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const action_erase_permissions_from_sc_memory{ + "action_erase_permissions_from_sc_memory", + ScType::ConstNodeClass}; + _SC_EXTERN static inline ScKeynode const binary_type{"binary_type", ScType::ConstNodeClass}; _SC_EXTERN static inline ScKeynode const binary_float{"binary_float", ScType::ConstNodeClass}; _SC_EXTERN static inline ScKeynode const binary_double{"binary_double", ScType::ConstNodeClass}; diff --git a/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_keynodes.cpp b/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_keynodes.cpp index 3e2d918b1d..5f3a65fdb4 100644 --- a/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_keynodes.cpp +++ b/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_keynodes.cpp @@ -108,6 +108,37 @@ TEST_F(ScKeynodesTest, CoreKeynodes) EXPECT_TRUE(ScKeynodes::sc_event_before_change_link_content.IsValid()); EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::sc_event_before_change_link_content) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::concept_guest_user.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::concept_guest_user) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::nrel_identified_user.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::nrel_identified_user) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::concept_authentication_request_user.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::concept_authentication_request_user) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::concept_authenticated_user.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::concept_authenticated_user) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::nrel_user_action_class.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::nrel_user_action_class) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::nrel_users_set_action_class.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::nrel_users_set_action_class) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::nrel_user_action_class_within_sc_structure.IsValid()); + EXPECT_TRUE( + m_ctx->GetElementType(ScKeynodes::nrel_user_action_class_within_sc_structure) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::nrel_users_set_action_class_within_sc_structure.IsValid()); + EXPECT_TRUE( + m_ctx->GetElementType(ScKeynodes::nrel_users_set_action_class_within_sc_structure) == ScType::ConstNodeNonRole); + EXPECT_TRUE(ScKeynodes::action_read_from_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_read_from_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::action_generate_in_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_generate_in_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::action_erase_from_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_erase_from_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::action_read_permissions_from_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_read_permissions_from_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::action_generate_permissions_in_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_generate_permissions_in_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::action_erase_permissions_from_sc_memory.IsValid()); + EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::action_erase_permissions_from_sc_memory) == ScType::ConstNodeClass); + EXPECT_TRUE(ScKeynodes::binary_type.IsValid()); EXPECT_TRUE(m_ctx->GetElementType(ScKeynodes::binary_type) == ScType::ConstNodeClass); EXPECT_TRUE(ScKeynodes::binary_float.IsValid()); diff --git a/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_memory_context.cpp b/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_memory_context.cpp index 2606bdef3f..70d64367c4 100644 --- a/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_memory_context.cpp +++ b/sc-memory/sc-memory/tests/sc-memory/units/common/test_sc_memory_context.cpp @@ -33,9 +33,8 @@ void TestAddPermissionsForUserToInitActions( ScAddr const & actionClassAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & nrelUserActionClassAddr{nrel_user_action_class_addr}; ScAddr const & arcAddr = context->GenerateConnector(ScType::ConstCommonArc, userAddr, actionClassAddr); - context->GenerateConnector(arcType, nrelUserActionClassAddr, arcAddr); + context->GenerateConnector(arcType, ScKeynodes::nrel_user_action_class, arcAddr); } void TestAddPermissionsForUserToInitReadActions( @@ -52,8 +51,7 @@ void TestAddPermissionsForUserToInitWriteActions( ScAddr const & userAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & writeActionInScMemoryAddr{action_generate_in_sc_memory_addr}; - TestAddPermissionsForUserToInitActions(context, userAddr, writeActionInScMemoryAddr, arcType); + TestAddPermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_generate_in_sc_memory, arcType); } void TestAddPermissionsForUserToInitEraseActions( @@ -61,8 +59,7 @@ void TestAddPermissionsForUserToInitEraseActions( ScAddr const & userAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & eraseActionInScMemoryAddr{action_erase_from_sc_memory_addr}; - TestAddPermissionsForUserToInitActions(context, userAddr, eraseActionInScMemoryAddr, arcType); + TestAddPermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_erase_from_sc_memory, arcType); } void TestAddAllPermissionsForUserToInitActions( @@ -80,9 +77,8 @@ void TestRemovePermissionsForUserToInitActions( ScAddr const & userAddr, ScAddr const & actionClassAddr) { - ScAddr const & nrelUserActionClassAddr{nrel_user_action_class_addr}; ScIterator5Ptr it5 = context->CreateIterator5( - userAddr, ScType::ConstCommonArc, actionClassAddr, ScType::ConstTempPosArc, nrelUserActionClassAddr); + userAddr, ScType::ConstCommonArc, actionClassAddr, ScType::ConstTempPosArc, ScKeynodes::nrel_user_action_class); EXPECT_TRUE(it5->Next()); ScAddr const & arcAddr = it5->Get(3); context->EraseElement(arcAddr); @@ -92,8 +88,7 @@ void TestRemovePermissionsForUserToInitReadActions( std::unique_ptr const & context, ScAddr const & userAddr) { - ScAddr const & readActionInScMemoryAddr{action_read_from_sc_memory_addr}; - TestRemovePermissionsForUserToInitActions(context, userAddr, readActionInScMemoryAddr); + TestRemovePermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_read_from_sc_memory); } void TestAddPermissionsForUsersSetToInitActions( @@ -102,9 +97,8 @@ void TestAddPermissionsForUsersSetToInitActions( ScAddr const & actionClassAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & nrelUsersSetActionClassAddr{nrel_users_set_action_class_addr}; ScAddr const & arcAddr = context->GenerateConnector(ScType::ConstCommonArc, usersSetAddr, actionClassAddr); - context->GenerateConnector(arcType, nrelUsersSetActionClassAddr, arcAddr); + context->GenerateConnector(arcType, ScKeynodes::nrel_users_set_action_class, arcAddr); } void TestAddPermissionsForUsersSetToInitReadActions( @@ -112,8 +106,7 @@ void TestAddPermissionsForUsersSetToInitReadActions( ScAddr const & usersSetAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & readActionInScMemoryAddr{action_read_from_sc_memory_addr}; - TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, readActionInScMemoryAddr, arcType); + TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, ScKeynodes::action_read_from_sc_memory, arcType); } void TestAddPermissionsForUsersSetToInitWriteActions( @@ -121,8 +114,7 @@ void TestAddPermissionsForUsersSetToInitWriteActions( ScAddr const & usersSetAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & writeActionInScMemoryAddr{action_generate_in_sc_memory_addr}; - TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, writeActionInScMemoryAddr, arcType); + TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, ScKeynodes::action_generate_in_sc_memory, arcType); } void TestAddPermissionsForUsersSetToInitEraseActions( @@ -130,8 +122,7 @@ void TestAddPermissionsForUsersSetToInitEraseActions( ScAddr const & usersSetAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & eraseActionInScMemoryAddr{action_erase_from_sc_memory_addr}; - TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, eraseActionInScMemoryAddr, arcType); + TestAddPermissionsForUsersSetToInitActions(context, usersSetAddr, ScKeynodes::action_erase_from_sc_memory, arcType); } void TestAddAllPermissionsForUsersSetToInitActions( @@ -149,9 +140,12 @@ void TestRemovePermissionsForUsersSetToInitActions( ScAddr const & userAddr, ScAddr const & actionClassAddr) { - ScAddr const & nrelUsersSetActionClassAddr{nrel_users_set_action_class_addr}; ScIterator5Ptr it5 = context->CreateIterator5( - userAddr, ScType::ConstCommonArc, actionClassAddr, ScType::ConstTempPosArc, nrelUsersSetActionClassAddr); + userAddr, + ScType::ConstCommonArc, + actionClassAddr, + ScType::ConstTempPosArc, + ScKeynodes::nrel_users_set_action_class); EXPECT_TRUE(it5->Next()); ScAddr const & arcAddr = it5->Get(3); context->EraseElement(arcAddr); @@ -161,8 +155,7 @@ void TestRemovePermissionsForUsersSetToInitReadActions( std::unique_ptr const & context, ScAddr const & userAddr) { - ScAddr const & readActionInScMemoryAddr{action_read_from_sc_memory_addr}; - TestRemovePermissionsForUsersSetToInitActions(context, userAddr, readActionInScMemoryAddr); + TestRemovePermissionsForUsersSetToInitActions(context, userAddr, ScKeynodes::action_read_from_sc_memory); } ScAddr TestGenerateClassForUser( @@ -189,8 +182,7 @@ void TestAuthenticationRequestUser( ScAddr const & userAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & conceptAuthenticationRequestUserAddr{concept_authentication_request_user_addr}; - context->GenerateConnector(arcType, conceptAuthenticationRequestUserAddr, userAddr); + context->GenerateConnector(arcType, ScKeynodes::concept_authentication_request_user, userAddr); } void TestReadActionsSuccessfully(std::unique_ptr const & context, TestScMemoryContext & userContext) @@ -411,9 +403,21 @@ void TestSetIdentifiedUser( ScAddr const & userAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & nrelIdentifiedUserAddr{nrel_identified_user_addr}; ScAddr const & arcAddr = context->GenerateConnector(ScType::ConstCommonArc, guestUserAddr, userAddr); - context->GenerateConnector(arcType, nrelIdentifiedUserAddr, arcAddr); + context->GenerateConnector(ScType::ConstTempNegArc, ScKeynodes::nrel_identified_user, arcAddr); + + auto eventWaiter = context->CreateConditionWaiter>( + arcAddr, + [&]() -> void + { + context->GenerateConnector(arcType, ScKeynodes::nrel_identified_user, arcAddr); + }, + [&](ScEventBeforeEraseIncomingArc const & event) -> bool + { + return event.GetArcSourceElement() == ScKeynodes::nrel_identified_user; + }); + + eventWaiter->Wait(200); } TEST_F(ScMemoryTestWithUserMode, HandleElementsByIdentifiedUser) @@ -424,11 +428,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByIdentifiedUser) ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestSetIdentifiedUser(m_ctx, guestUserAddr, userAddr); - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -460,11 +463,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserGeneratedBefor ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -487,11 +489,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserGeneratedBefor ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -517,11 +518,10 @@ TEST_F( ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -578,11 +578,10 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByInvalidConnectorToUser) ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isChecked = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&isChecked](ScEventAfterGenerateOutgoingArc const &) { isChecked = true; @@ -605,13 +604,13 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByInvalidConnectorToUser) EXPECT_TRUE(isChecked.load()); eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&isChecked](ScEventAfterGenerateOutgoingArc const &) { isChecked = false; }); - ScIterator3Ptr it3 = m_ctx->CreateIterator3(conceptAuthenticatedUserAddr, ScType::ConstCommonArc, userAddr); + ScIterator3Ptr it3 = m_ctx->CreateIterator3(ScKeynodes::concept_authenticated_user, ScType::ConstCommonArc, userAddr); while (it3->Next()) { m_ctx->EraseElement(it3->Get(2)); @@ -626,11 +625,10 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByInvalidConnectorToUsersSet) ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isChecked = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&isChecked](ScEventAfterGenerateOutgoingArc const &) { isChecked = true; @@ -654,13 +652,13 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByInvalidConnectorToUsersSet) EXPECT_TRUE(isChecked.load()); eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&isChecked](ScEventAfterGenerateOutgoingArc const &) { isChecked = false; }); - ScIterator3Ptr it3 = m_ctx->CreateIterator3(conceptAuthenticatedUserAddr, ScType::ConstCommonArc, userAddr); + ScIterator3Ptr it3 = m_ctx->CreateIterator3(ScKeynodes::concept_authenticated_user, ScType::ConstCommonArc, userAddr); while (it3->Next()) { m_ctx->EraseElement(it3->Get(2)); @@ -675,11 +673,10 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByUserWithInvalidConnectorsToPe ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isChecked = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isChecked](ScEventAfterGenerateOutgoingArc const &) { TestActionsUnsuccessfully(m_ctx, userContext); @@ -696,12 +693,10 @@ TEST_F(ScMemoryTestWithUserMode, NoHandleElementsByUserWithInvalidConnectorsToPe TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserGeneratedAfter) { - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; - std::atomic_bool isChecked = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &isChecked](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -723,12 +718,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserGeneratedAfter TEST_F(ScMemoryTestWithUserMode, SeveralHandleElementsByAuthenticatedUserGeneratedAfter) { - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; - std::atomic_bool isChecked = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &isChecked](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -766,13 +759,11 @@ TEST_F( ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; - std::atomic_bool isAuthenticated = false; { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -793,7 +784,7 @@ TEST_F( { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempNegArc); @@ -804,7 +795,8 @@ TEST_F( isAuthenticated = false; }); - ScIterator3Ptr const it3 = m_ctx->CreateIterator3(conceptAuthenticatedUserAddr, ScType::ConstTempPosArc, userAddr); + ScIterator3Ptr const it3 = + m_ctx->CreateIterator3(ScKeynodes::concept_authenticated_user, ScType::ConstTempPosArc, userAddr); EXPECT_TRUE(it3->Next()); m_ctx->EraseElement(it3->Get(1)); @@ -812,12 +804,12 @@ TEST_F( EXPECT_FALSE(isAuthenticated.load()); } - EXPECT_TRUE(m_ctx->CheckConnector(conceptAuthenticatedUserAddr, userAddr, ScType::ConstTempNegArc)); + EXPECT_TRUE(m_ctx->CheckConnector(ScKeynodes::concept_authenticated_user, userAddr, ScType::ConstTempNegArc)); { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -835,8 +827,8 @@ TEST_F( EXPECT_TRUE(isAuthenticated.load()); } - EXPECT_FALSE(m_ctx->CheckConnector(conceptAuthenticatedUserAddr, userAddr, ScType::ConstTempNegArc)); - EXPECT_TRUE(m_ctx->CheckConnector(conceptAuthenticatedUserAddr, userAddr, ScType::ConstTempPosArc)); + EXPECT_FALSE(m_ctx->CheckConnector(ScKeynodes::concept_authenticated_user, userAddr, ScType::ConstTempNegArc)); + EXPECT_TRUE(m_ctx->CheckConnector(ScKeynodes::concept_authenticated_user, userAddr, ScType::ConstTempPosArc)); } TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutPermissions) @@ -844,11 +836,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutPermiss ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -868,11 +859,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutWriteAn ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -897,11 +887,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutErasePe ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -927,11 +916,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutWritePe ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -957,11 +945,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutReadAnd ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -986,11 +973,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutReadPer ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1016,11 +1002,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithoutReadAnd ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1045,12 +1030,11 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithReadPermis ScAddr const & userAddr = m_ctx->GenerateNode(ScType::ConstNode); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; { std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1070,11 +1054,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithReadPermis EXPECT_TRUE(isAuthenticated.load()); } - ScAddr const & nrelUserActionClassAddr{nrel_user_action_class_addr}; std::atomic_bool isPermissionsUpdated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - nrelUserActionClassAddr, + ScKeynodes::nrel_user_action_class, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempNegArc); @@ -1101,12 +1084,11 @@ TEST_F( ScAddr const & usersSetAddr = TestGenerateClassForUser(m_ctx, userAddr); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; { std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1126,11 +1108,10 @@ TEST_F( EXPECT_TRUE(isAuthenticated.load()); } - ScAddr const & nrelUsersSetActionClassAddr{nrel_users_set_action_class_addr}; std::atomic_bool isPermissionsUpdated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - nrelUsersSetActionClassAddr, + ScKeynodes::nrel_users_set_action_class, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempNegArc); @@ -1230,24 +1211,21 @@ void TestReadWriteEraseAccessedAllElementsSuccessfully( void TestAddPermissionsToHandleReadPermissions(std::unique_ptr const & context, ScAddr const & userAddr) { - ScAddr const & readActionInScMemoryAddr{action_read_permissions_from_sc_memory_addr}; - TestAddPermissionsForUserToInitActions(context, userAddr, readActionInScMemoryAddr); + TestAddPermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_read_permissions_from_sc_memory); } void TestAddPermissionsToHandleWritePermissions( std::unique_ptr const & context, ScAddr const & userAddr) { - ScAddr const & writeActionInScMemoryAddr{action_generate_permissions_in_sc_memory_addr}; - TestAddPermissionsForUserToInitActions(context, userAddr, writeActionInScMemoryAddr); + TestAddPermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_generate_permissions_in_sc_memory); } void TestAddPermissionsToHandleErasePermissions( std::unique_ptr const & context, ScAddr const & userAddr) { - ScAddr const & eraseActionInScMemoryAddr{action_erase_permissions_from_sc_memory_addr}; - TestAddPermissionsForUserToInitActions(context, userAddr, eraseActionInScMemoryAddr); + TestAddPermissionsForUserToInitActions(context, userAddr, ScKeynodes::action_erase_permissions_from_sc_memory); } void TestAddAllPermissionsToHandleAllPermissions( @@ -1265,11 +1243,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleAccessedElementsByAuthenticatedUserWithou TestScMemoryContext userContext{userAddr}; { - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1295,11 +1272,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleAccessedElementsByAuthenticatedUserWithPe TestScMemoryContext userContext{userAddr}; { - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [this, &userContext, &isAuthenticated](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1327,12 +1303,11 @@ void TestAddPermissionsForUserToInitActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & nrelUserActionClassWithinScStructureAddr{nrel_user_action_class_within_sc_structure_addr}; ScAddr const & arcBetweenActionAndStructureAddr = context->GenerateConnector(ScType::ConstCommonArc, actionClassAddr, structureAddr); ScAddr const & arcAddr = context->GenerateConnector(ScType::ConstCommonArc, userAddr, arcBetweenActionAndStructureAddr); - context->GenerateConnector(arcType, nrelUserActionClassWithinScStructureAddr, arcAddr); + context->GenerateConnector(arcType, ScKeynodes::nrel_user_action_class_within_sc_structure, arcAddr); } void TestAddPermissionsForUserToInitReadActionsWithinStructure( @@ -1341,9 +1316,8 @@ void TestAddPermissionsForUserToInitReadActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & readActionInScMemoryAddr{action_read_from_sc_memory_addr}; TestAddPermissionsForUserToInitActionsWithinStructure( - context, userAddr, readActionInScMemoryAddr, structureAddr, arcType); + context, userAddr, ScKeynodes::action_read_from_sc_memory, structureAddr, arcType); } void TestAddPermissionsForUserToInitWriteActionsWithinStructure( @@ -1352,9 +1326,8 @@ void TestAddPermissionsForUserToInitWriteActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & writeActionInScMemoryAddr{action_generate_in_sc_memory_addr}; TestAddPermissionsForUserToInitActionsWithinStructure( - context, userAddr, writeActionInScMemoryAddr, structureAddr, arcType); + context, userAddr, ScKeynodes::action_generate_in_sc_memory, structureAddr, arcType); } void TestAddPermissionsForUserToInitEraseActionsWithinStructure( @@ -1363,9 +1336,8 @@ void TestAddPermissionsForUserToInitEraseActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & eraseActionInScMemoryAddr{action_erase_from_sc_memory_addr}; TestAddPermissionsForUserToInitActionsWithinStructure( - context, userAddr, eraseActionInScMemoryAddr, structureAddr, arcType); + context, userAddr, ScKeynodes::action_erase_from_sc_memory, structureAddr, arcType); } void TestAddPermissionsForUsersSetToInitActionsWithinStructure( @@ -1375,12 +1347,11 @@ void TestAddPermissionsForUsersSetToInitActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & nrelUsersSetActionClassWithinScStructureAddr{nrel_users_set_action_class_within_sc_structure_addr}; ScAddr const & arcBetweenActionAndStructureAddr = context->GenerateConnector(ScType::ConstCommonArc, actionClassAddr, structureAddr); ScAddr const & arcAddr = context->GenerateConnector(ScType::ConstCommonArc, usersSetAddr, arcBetweenActionAndStructureAddr); - context->GenerateConnector(arcType, nrelUsersSetActionClassWithinScStructureAddr, arcAddr); + context->GenerateConnector(arcType, ScKeynodes::nrel_users_set_action_class_within_sc_structure, arcAddr); } void TestAddPermissionsForUsersSetToInitReadActionsWithinStructure( @@ -1389,9 +1360,8 @@ void TestAddPermissionsForUsersSetToInitReadActionsWithinStructure( ScAddr const & structureAddr, ScType const & arcType = ScType::ConstTempPosArc) { - ScAddr const & readActionInScMemoryAddr{action_read_from_sc_memory_addr}; TestAddPermissionsForUsersSetToInitActionsWithinStructure( - context, usersSetAddr, readActionInScMemoryAddr, structureAddr, arcType); + context, usersSetAddr, ScKeynodes::action_read_from_sc_memory, structureAddr, arcType); } void TestReadActionsWithinStructureWithConnectorAndIncidentElementsSuccessfully( @@ -1569,11 +1539,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsSuccessfully( @@ -1601,11 +1570,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserHavingClassWit m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsSuccessfully( @@ -1636,11 +1604,10 @@ TEST_F( m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsUnsuccessfully(userContext, nodeAddr1); @@ -1710,11 +1677,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalWrite m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1743,11 +1709,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalErase m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1776,11 +1741,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalWrite m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -1812,13 +1776,11 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; - std::atomic_bool isAuthenticated = false; { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsSuccessfully( @@ -1837,7 +1799,8 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP EXPECT_TRUE(isAuthenticated.load()); } - ScIterator3Ptr it3 = m_ctx->CreateIterator3(conceptAuthenticatedUserAddr, ScType::ConstTempPosArc, userAddr); + ScIterator3Ptr it3 = + m_ctx->CreateIterator3(ScKeynodes::concept_authenticated_user, ScType::ConstTempPosArc, userAddr); EXPECT_TRUE(it3->Next()); m_ctx->EraseElement(it3->Get(1)); isAuthenticated = false; @@ -1845,7 +1808,7 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsUnsuccessfully(userContext, nodeAddr2); @@ -1856,9 +1819,8 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP isAuthenticated = true; }); - ScAddr const & nrelUserActionClassWithinScStructureAddr{nrel_user_action_class_within_sc_structure_addr}; it3 = m_ctx->CreateIterator3( - nrelUserActionClassWithinScStructureAddr, ScType::ConstTempPosArc, ScType::ConstCommonArc); + ScKeynodes::nrel_user_action_class_within_sc_structure, ScType::ConstTempPosArc, ScType::ConstCommonArc); EXPECT_TRUE(it3->Next()); m_ctx->EraseElement(it3->Get(1)); @@ -1880,13 +1842,11 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserHavingClassWit m_ctx, nodeAddr1, arcAddr, linkAddr, relationEdgeAddr, relationAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; - std::atomic_bool isAuthenticated = false; { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsSuccessfully( @@ -1905,7 +1865,8 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserHavingClassWit EXPECT_TRUE(isAuthenticated.load()); } - ScIterator3Ptr it3 = m_ctx->CreateIterator3(conceptAuthenticatedUserAddr, ScType::ConstTempPosArc, userAddr); + ScIterator3Ptr it3 = + m_ctx->CreateIterator3(ScKeynodes::concept_authenticated_user, ScType::ConstTempPosArc, userAddr); EXPECT_TRUE(it3->Next()); m_ctx->EraseElement(it3->Get(1)); isAuthenticated = false; @@ -1913,7 +1874,7 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserHavingClassWit { auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const &) { TestReadActionsWithinStructureWithConnectorAndIncidentElementsUnsuccessfully(userContext, nodeAddr2); @@ -1924,9 +1885,8 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserHavingClassWit isAuthenticated = true; }); - ScAddr const & nrelUsersSetActionClassWithinScStructureAddr{nrel_users_set_action_class_within_sc_structure_addr}; it3 = m_ctx->CreateIterator3( - nrelUsersSetActionClassWithinScStructureAddr, ScType::ConstTempPosArc, ScType::ConstCommonArc); + ScKeynodes::nrel_users_set_action_class_within_sc_structure, ScType::ConstTempPosArc, ScType::ConstCommonArc); EXPECT_TRUE(it3->Next()); m_ctx->EraseElement(it3->Get(1)); @@ -2001,11 +1961,10 @@ TEST_F( ScAddr const & structureAddr = TestGenerateStructureWithConnectorAndSource(m_ctx, nodeAddr1, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -2088,11 +2047,10 @@ TEST_F( ScAddr const & structureAddr = TestGenerateStructureWithConnectorAndTarget(m_ctx, linkAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -2162,11 +2120,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP ScAddr const & structureAddr = TestGenerateStructureWithConnector(m_ctx, arcAddr, nodeAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc); @@ -2227,11 +2184,10 @@ TEST_F(ScMemoryTestWithUserMode, HandleElementsByAuthenticatedUserWithLocalReadP ScAddr const & structureAddr = TestGenerateStructureWithLinks(m_ctx, linkAddr1, linkAddr2); TestScMemoryContext userContext{userAddr}; - ScAddr const & conceptAuthenticatedUserAddr{concept_authenticated_user_addr}; std::atomic_bool isAuthenticated = false; auto eventSubscription = m_ctx->CreateElementaryEventSubscription>( - conceptAuthenticatedUserAddr, + ScKeynodes::concept_authenticated_user, [&](ScEventAfterGenerateOutgoingArc const & event) { EXPECT_EQ(event.GetArcType(), ScType::ConstTempPosArc);