66from openhound .core .asset import BaseAsset , EdgeDef , NodeDef
77from openhound .core .models .entries_dataclass import Edge , EdgePath , EdgeProperties
88
9- from openhound_github .graph import GHNode , GHNodeProperties
9+ from openhound_github .graph import GHEdgeProperties , GHNode , GHNodeProperties
1010from openhound_github .kinds import edges as ek
1111from openhound_github .kinds import nodes as nk
1212from openhound_github .main import app
1515@dataclass
1616class GHOrgSecretProperties (GHNodeProperties ):
1717 """Org secret properties and accordion panel queries.
18-
18+
1919 Attributes:
2020 visibility: The secret's visibility scope: `all` (all repos), `private` (private and internal repos), or `selected` (specific repos).
2121 environment_name: The name of the environment (GitHub organization).
@@ -55,6 +55,13 @@ class GHOrgSecretProperties(GHNodeProperties):
5555 description = "Repository can access org secret" ,
5656 traversable = True ,
5757 ),
58+ EdgeDef (
59+ start = nk .ORG_ROLE ,
60+ end = nk .ORG_SECRET ,
61+ kind = ek .CAN_READ_SECRET ,
62+ description = "Org role can read org secret by creating a repository in scope" ,
63+ traversable = True ,
64+ ),
5865 ],
5966)
6067class OrgSecret (BaseAsset ):
@@ -96,6 +103,15 @@ def as_node(self) -> GHNode:
96103 ),
97104 )
98105
106+ def _read_secret_query (self , role_node_id : str ) -> str :
107+ return (
108+ f"MATCH p=(:GH_OrgRole {{node_id:'{ role_node_id } '}})"
109+ f"-[:GH_CanCreateRepositories|GH_CanCreatePublicRepositories|"
110+ f"GH_CanCreateInternalRepositories|GH_CanCreatePrivateRepositories]->"
111+ f"(:GH_Organization)-[:GH_Contains]->"
112+ f"(:GH_OrgSecret {{node_id:'{ self .node_id } '}}) RETURN p"
113+ )
114+
99115 @property
100116 def _all_repo_edges (self ):
101117 if self .visibility == "all" :
@@ -111,7 +127,9 @@ def _all_repo_edges(self):
111127 @property
112128 def _private_repo_edges (self ):
113129 if self .visibility == "private" :
114- for repo in self ._lookup .private_repository_node_ids_for_org (self .org_login ):
130+ for repo in self ._lookup .private_repository_node_ids_for_org (
131+ self .org_login
132+ ):
115133 for repo_node_id in repo :
116134 yield Edge (
117135 kind = ek .HAS_SECRET ,
@@ -121,15 +139,50 @@ def _private_repo_edges(self):
121139 )
122140
123141 @property
124- def edges (self ):
142+ def _contains_edge (self ):
125143 yield Edge (
126144 kind = ek .CONTAINS ,
127145 start = EdgePath (value = self .org_node_id , match_by = "id" ),
128146 end = EdgePath (value = self .node_id , match_by = "id" ),
129147 properties = EdgeProperties (traversable = False ),
130148 )
149+
150+ @property
151+ def _composed_read_secret_edges (self ):
152+ if self .visibility != "all" :
153+ return
154+
155+ owners_role_id = f"{ self .org_node_id } _owners"
156+ yield Edge (
157+ kind = ek .CAN_READ_SECRET ,
158+ start = EdgePath (value = owners_role_id , match_by = "id" ),
159+ end = EdgePath (value = self .node_id , match_by = "id" ),
160+ properties = GHEdgeProperties (
161+ traversable = True ,
162+ composed = True ,
163+ query_composition = self ._read_secret_query (owners_role_id ),
164+ ),
165+ )
166+
167+ if self ._lookup .members_can_create_repository (self .org_login ):
168+ members_role_id = f"{ self .org_node_id } _members"
169+ yield Edge (
170+ kind = ek .CAN_READ_SECRET ,
171+ start = EdgePath (value = members_role_id , match_by = "id" ),
172+ end = EdgePath (value = self .node_id , match_by = "id" ),
173+ properties = GHEdgeProperties (
174+ traversable = True ,
175+ composed = True ,
176+ query_composition = self ._read_secret_query (members_role_id ),
177+ ),
178+ )
179+
180+ @property
181+ def edges (self ):
182+ yield from self ._contains_edge
131183 yield from self ._all_repo_edges
132184 yield from self ._private_repo_edges
185+ yield from self ._composed_read_secret_edges
133186
134187
135188@app .asset (
@@ -164,17 +217,24 @@ def as_node(self) -> None:
164217 return None
165218
166219 @property
167- def edges (self ):
220+ def _contains_edge (self ):
168221 yield Edge (
169222 kind = ek .CONTAINS ,
170223 start = EdgePath (value = self .org_node_id , match_by = "id" ),
171224 end = EdgePath (value = self .node_id , match_by = "id" ),
172225 properties = EdgeProperties (traversable = False ),
173226 )
174227
228+ @property
229+ def _has_secret_edge (self ):
175230 yield Edge (
176231 kind = ek .HAS_SECRET ,
177232 start = EdgePath (value = self .repository_node_id , match_by = "id" ),
178233 end = EdgePath (value = self .node_id , match_by = "id" ),
179234 properties = EdgeProperties (traversable = True ),
180235 )
236+
237+ @property
238+ def edges (self ):
239+ yield from self ._contains_edge
240+ yield from self ._has_secret_edge
0 commit comments