Encryption based on a tree structure - encryption

This may be more of an academic question but I've got a tree of users like such:
1->2
1->3
2->4
2->5
Each user needs to be able to examine themselves and their subgroup there is no limit to the number of subgroups and there's no limit to the number of users. No user should be able to examine any other user's subgroup. So even though 2 and 3 are the same level 2 cannot examine 3's subs and vice versa.
What encryption scheme would let me do the fewest number of checks to retrieve the whole tree?

Example graphic of the item arrangement for the following description.
/- 4
/- 2 -|
| \- 5
1 -|
|
\- 3
Encrypt each item with its own key.
Include the key of each item in its parent.
To allow access to any item and its subtree, supply the key to that item.
To allow access to item 2 and its sub-items provide the encryption to item 2.
Then sub-items 4 and 5 can be accessed because their keys are in item 2.
Allowing access to item 3 will not provide the keys to items 1, 2, 4 and 5.
If including the key in each parent item is not desirable create a shadow tree just for the keys.

Related

Preventing cycles in a neo4j graph where relationships are dated

Note: I apologize for not being able to include the images directly in the post, I don't have enough reputation in stackoverflow yet.
I'm brand new to graph databases, but I'm trying to understand if a graph database is suited for my problem. Here we go!
I have a set of users who can relate to each other via a "Parent" relationship (i.e., they can be built into a tree / hierarchy). The "Parent" relationship from one user to another is said to "begin" as of a certain date, and the relationship only "ends" if/when another "Parent" relationships exists between the same users and with a later date.
Every user can have <= 1 parent as of any particular date, and can have >=0 children. I.e., at most one parent at a time, and no limit to the number of children.
I've read blog posts dealing with dated relationships, but they don't seem to address this level of complexity:
https://maxdemarzi.com/2015/08/26/modeling-airline-flights-in-neo4j/
https://maxdemarzi.com/2017/05/24/flight-search-with-neo4j/
My challenge:
For a given set of users with existing "Parent" relationships, determine whether a new "Parent" relationship can be added "as of" a certain date WITHOUT creating a cycle anywhere in the timeline.
To help visualize an example, imagine we have four users Alice, Bob, Carlos, and David.
-----------------------------------------
| User | Date | Parent |
|-----------|---------------|-----------|
| Alice | 09/13/2012 | Bob |
| Alice | 04/01/2021 | David |
| Bob | 01/31/2020 | Carlos |
| Carlos | 02/14/2008 | David |
-----------------------------------------
Here is a (highly abstract) picture representing the current state of the data (time flows to the right):
[Initial state of the data as timeline]
https://i.stack.imgur.com/qdcbL.png
So in this example Alice has Bob as a parent from 9/13/2012 until 4/1/2021, at which point she begins to have David as a parent. Bob has no parent until 1/31/2020, at which point he gets Carlos as a parent. Etc.
I need to be able to determine whether an update/insert will create a cycle in the "parent" hierarchy at any point in time. So, for example, I'd like to be able to determine that it would be INVALID to set Carlos's parent to be Alice as of 10/22/2020 because then there would be a cycle in the hierarchy for the period between 10/22/2020 and 4/1/2021 (i.e., Alice-->Bob-->Carlos-->Alice). To help visualize it:
[Invalid addition creates a cycle in the timeline]
https://i.stack.imgur.com/xA2vv.png
But I also need to be able to determine that it would be VALID to set Carlos's parent to Alice as of 10/22/2021, as drawn here:
[Valid addition with no cycles in timeline]
https://i.stack.imgur.com/9u0P4.png
In terms of modeling the data, I started by thinking of two different models.
First:
I tried having my only nodes be "Users," and having my "Parent" relationships include a date in the relationship type. Since the range of dates is huge and the dates themselves are not known in advance, I'm not sure this is a good idea but decided to give it a shot anyway.
Diagram:
[graph diagram with dated relationships]
https://i.stack.imgur.com/ZuPDR.png
Cypher:
CREATE (n0:User {name: "Alice"})-[:P_2012_09_13]->(:User {name: "Bob"})-[:P_2020_01_31]->(:User {name: "Carlos"})-[:P_2008_02_14]->(:User {name: "David"})<-[:P_2021_04_01]-(n0)
Second:
I tried creating "UserDay" nodes to capture the date element, thereby reducing the range of relationship types to only two (i.e., a 1:many "HAS" relationship from User to UserDay, then a 1:1 "P" relationship from UserDay to User).
Diagram:
[graph diagram with user-days]
https://i.stack.imgur.com/W60bp.png
Cypher:
CREATE (n8:UserDay {date: "2021-04-01"})<-[:HAS]-(:User {name: "Alice"})-[:HAS]->(:UserDay {date: "2012-09-13"})-[:P]->(:User {name: "Bob"})-[:HAS]->(:UserDay {date: "2020-01-31"})-[:P]->(:User {name: "Carlos"})-[:HAS]->(:UserDay {date: "2008-02-14"})-[:P]->(:User {name: "David"})<-[:P]-(n8)
Given a source User, destination User, and start date, I need to be able to determine if a cycle would be created in the hierarchy for any time in the timeline.
Carlos, Alice, 10/22/2020 ----> should be invalid
Carlos, Alice, 10/22/2021 ----> should be valid
I've been spinning my wheels reading through neo4j docs and googling, and finally decided to ask my very first question on stackoverflow! Please let me know if you have any questions or if anything I've said is unclear.
Thanks in advance!

Compound Resource IDs versus URL IDs

I have two resources with a strict parent/child hierarchical relationship, where the child has no existence without the parent, and where the child ID must be a monotonically increasing integer starting from 1 within the parent resource, so not unique within the global resource set. Lets call them Foo and Bar, where Foo is the parent:
Foo: ABC
|- Bar: 1
|- Bar: 2
|- Bar: 3
Foo: QWE
|- Bar: 1
|- Bar: 2
Within the database, we store this in a table with a simple compound natural key:
Foo | Bar | Value
===================
ABC | 1 | shizzle
ABC | 2 | bizzle
ABC | 3 | fizzle
QWE | 1 | lorem
QWE | 2 | ipsum
The standard requires that the Type / ID combination must be unique within the api to allow included resources to be correctly linked to, so to create a unique Bar ID here we would have to join the compound key as say Foo_Bar, i.e. ABC_1 and QWE_1. Ugly and bringing some issues around the client needing to have knowledge of the key composition and the joining char, but fair enough, and we can always add the natural key as either data or meta for the client to use instead.
My question comes with the url for the child resource. For internal consistency with the document ID, the url might look like:
https://example.com/api/v1/foos/ABC/bars/ABC_1
but that seems rather redundant repeating the 'ABC', not to mention ugly, and inconsistent with our main website urls. I'd much prefer using:
https://example.com/api/v1/foos/ABC/bars/1
I think I'm free to do what I want, but I suspect this may cause issues for some of the libraries out there if they make the assumption that they are the same? In general are urls required to have any logical relationship to the internal Resource Type/ID?
Related to this, can the Resource ID use a '.' to join the composite key instead of a '_'? This would make it consistent wth the relationship paths, so 'foos.bars' = 'ABC.1'. While the standard prohibits '.' in member names, there seems to be no such constraint on ID names?
Cheers!
John.
The specification is not absolute on the format url. Thought it recommends that urls match the resource's id.
From http://jsonapi.org/recommendations/#urls-individual-resources
Treat collections of resources as sets keyed by resource ID. The URL for an individual resource can be formed by appending the resource’s ID to the collection URL.
For example, a photo with an ID of "1" will have the URL:
/photos/1
Following this, your url to access the foo resource with id ABC_1 would be
https://example.com/api/v1/foos/ABC_1
and accordingly to get the bar resource with id 1
https://example.com/api/v1/bars/1
Regarding your example url https://example.com/api/v1/foos/ABC/bars/ABC_1, while not invalid, you won't find any similar example in the specification similar to resource_type/resource_id/relation_name/relation_id (with 4 nested levels).
The specification recommendation is to have 3 levels, which will return in your case an array of resource identifier objects:
resource_type/resource_id/relation_name
From http://jsonapi.org/recommendations/#urls-relationships
It is recommended that a relationship URL be formed by appending /relationships/ and the name of the relationship to the resource’s URL.
For example, a photo’s comments relationship will have the URL:
/photos/1/relationships/comments

QTreeView/QAbstractItemModel subtrees in multiple columns

I'm working on a subclass of QAbstractItemModel that plugs into a QTreeView. It has a recursive Name = Value type structure - any index could have its own subtree. This is fine on the left side, because almost every tree view out there works that way. The problem is that sometimes I want a subtree only on the right side - a list of values. As I have it right now, it seems like it should work, but Qt is never calling rowCount() for the right side, and never realizing that there should be a subtree there.
The solution that I have right now is basically to create a separate model for that, and use setIndexWidget to give it a separate tree view every time this happens. That's fine, but I'd really like to get the subtrees showing up on the right without having to throw tree views all over the place. My model responds that there are subtrees over there, but Qt just never asks for them.
If this is a little unclear, this is the basic idea of what I want to accomplish:
- Root |
- Name 1 | Value
Name 2 | - Compound Value
| Sub-value 1
| Sub-value 2
Name 3 | + Compound Value (collapsed)
+ Name 4 | Value
As it is, the compound values will not get the +'s and -'s next to them because Qt never calls hasChildren() or rowCount() in that column, even though my model would return that yes, there are children, if it was asked.
If I end up having to give it a sub-tree view, that's fine. I'd just like to be sure that there's not a better way to do it first.
I'm trying to implement a dual Tree View my self, some thing like
+ a | A
+ b | + B
c | C
and from What I've seen you can make the space between Name 2 and Name 3 by returning empty data e.g. an empty string under the Name 2 which would enable you to have a + infront of it.
So something like this may help
def data(self, index, role):
...
if item.pathdepth() > 3 :
return " "
...
def flags(self, index)
...
if item.pathdepth() > 3 :
return Qt.Some_Role but not others
...
I don't know enough about the roles yet, but you could disable selection and editing so that the 'blanks' are not selectabe by the user.
But I haven't worked out how to get a tree in the second column.

Is there a way to skip a level with telerik RadGrid in tree mode?

Here's the situation: I've got a two level tree that I'm displaying in a hierarchical RadGrid:
-Category 1
--Cat 1 Section 1
--Cat 1 Section 2
-Category 2
--Cat 2 Section 1
--Cat 2 Section 2
--Cat 2 Section 3
-Category 3
--Cat 3 Section 1
and so on. But I was just handed a new requirement that the categories themselves are actually children of another kind of entity:
-Bucket 1
--Bucket 1 Category tree...
-Bucket 2
--Bucket 2 Category tree...
The part of the requirement that I can't figure out how to express in the RadGrid is this (actually this is simplified from the whole ugly truth): if there are multiple buckets in the data set, they want the root level of the tree to be the buckets, but if there is only one bucket, they do not want the root to be that single bucket node; rather they just want the root level to be the categories in that lone bucket.
My problem is that I'm not seeing a way to remove that bucket level from the control and promote the next level to the root. Is there any way to do this? Thanks in advance.
It will all come down to the binding that you create. I don't think there is another way to do it.
if (ShowAll)
{
RadGrid1.DataSource = GetBucketsAll();
}
else
{
RadGrid1.DataSource = GetCategoriesByBucketId(id);
}
Then work your way thru the GridDetailTableDataBindEvent.

How to Query Nested Set model with multiple roots plus filtering

How do you query a nested set model with multiple roots, such trees in the same table? Currently, I added an extra column called the "Root" indicating the ID of the root node for all sub-tree nodes, however, I can't figure out the sql to retrieve them in the proper order
I'm referring to the article Managing Hierarchical Data in MySQL.
Normally, the query to retrieve the items out in order is by order the left leaf value, but with multiple roots, you can end up with multiple "left:1" one after another, such break the tree.
I'm currently using a solution completely not related to SQL. I re-arranged them in my C# code, but I'm just wondering if there is a way to do it with SQL and such save the time I spent on the web server
One last question. If I have a filter and it filters out some data out of the tree, how do you deal with it?
Say
Task 1 (In progress)
Task 2 (Active)
Task 3 (Active)
If the filter is to show all tree with status "Active", what do you do?
"Multiple roots" simply means that you're starting at the first level and omitting the "true" root altogether. So,
Root1 (1, 4)
Node1 (2, 3)
Root2 (5, 12)
Node21 (6, 7)
Node22 (8, 11)
Node221 (9, 10)
Do NOT restart the sequence on left / right indexes; you'd be walking into a world of hurt.
As far as your filter question goes, it's purely a matter of presentation. There are different ways to handle this; the one I used in the past was to show all nodes in the path leading to the node that satisfies your filter criteria but highlight "filtered out" nodes differently and make them non-actionable (e.g. can't be selected in UI, operations can't be performed on them, etc...). Something like:
Task 1 (In progress) [greyed out, inactive]
+Task 2 (Active)
+Task 3 (Active)
Another approach is to use grid / tree combo to display filter results where path to the node is shown flattened but nodes under the node (if any) are shown as tree. Something like:
Task1 -> Task 2 (Active)
+ Task 3 (Active)
Task1 -> Task 4 -> Task 6 (Active)
+ Task 7 (Active)

Resources