Skip to content

Commit

Permalink
first attempt at user schema, not yet in use
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Brauer <[email protected]>
  • Loading branch information
danbrauer committed Nov 8, 2024
1 parent 5f4e459 commit 55f6f36
Showing 1 changed file with 88 additions and 0 deletions.
88 changes: 88 additions & 0 deletions cartography/models/github/users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from dataclasses import dataclass
from typing import Optional

from cartography.models.core.common import PropertyRef
from cartography.models.core.nodes import CartographyNodeProperties
from cartography.models.core.nodes import CartographyNodeSchema
from cartography.models.core.relationships import CartographyRelProperties
from cartography.models.core.relationships import CartographyRelSchema
from cartography.models.core.relationships import LinkDirection
from cartography.models.core.relationships import make_target_node_matcher
from cartography.models.core.relationships import OtherRelationships
from cartography.models.core.relationships import TargetNodeMatcher


@dataclass(frozen=True)
class GitHubUserNodeProperties(CartographyNodeProperties):
id: PropertyRef = PropertyRef('url')
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
fullname: PropertyRef = PropertyRef('name')
username: PropertyRef = PropertyRef('login', extra_index=True)
# optional because some enterprise owners do not have this property specified
has_2fa_enabled: Optional[PropertyRef] = PropertyRef('hasTwoFactorEnabled')
role: PropertyRef = PropertyRef('role')
is_site_admin: PropertyRef = PropertyRef('isSiteAdmin')
is_enterprise_owner: PropertyRef = PropertyRef('isEnterpriseOwner')
email: PropertyRef = PropertyRef('email')
company: PropertyRef = PropertyRef('company')

@dataclass(frozen=True)
class GitHubUserToOrganizationRelProperties(CartographyRelProperties):
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)


@dataclass(frozen=True)
class GitHubUserMemberOfOrganizationRel(CartographyRelSchema):
target_node_label: str = 'GitHubOrganization'
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
{'id': PropertyRef('org_url', set_in_kwargs=True)},
)
direction: LinkDirection = LinkDirection.OUTWARD
rel_label: str = "MEMBER_OF"
properties: GitHubUserToOrganizationRelProperties = GitHubUserToOrganizationRelProperties()


@dataclass(frozen=True)
class GitHubUserUnaffiliatedOrganizationRel(CartographyRelSchema):
"""
See docs in GitHubUserSchema for more on what 'UNAFFILIATED' means.
"""
target_node_label: str = 'GitHubOrganization'
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
{'id': PropertyRef('org_url', set_in_kwargs=True)},
)
direction: LinkDirection = LinkDirection.OUTWARD
rel_label: str = "UNAFFILIATED"
properties: GitHubUserToOrganizationRelProperties = GitHubUserToOrganizationRelProperties()

@dataclass(frozen=True)
class GitHubUserSchema(CartographyNodeSchema):
"""
Note the relationship between GitHubUser and GitHubOrganization is implemented via 'other_relationships' and not via
the 'sub_resource_relationship' field as might be expected.
The 'sub_resource_relationship' typically describes the relationship of a node to its tenant (the org, project, or
other resource to which other nodes belong). An assumption of that relationship is that if the tenant goes
away, all nodes related to it should be cleaned up.
In GitHub, though the GitHubUser's tenant seems to be GitHubOrganization, users actually exist independently. There
is a concept of 'UNAFFILIATED' users, like Enterprise Owners who are related to an org even if they are not direct
members of it. You would not want them to be cleaned up, if an org goes away, and you could want them in your graph
even if they are not members of any org in the enterprise.
To allow for this in the schema, this relationship is treated as any other node-to-node relationship, via
'other_relationships', instead of as the typical 'sub_resource_relationship'.
See:
* https://docs.github.com/en/graphql/reference/enums#roleinorganization
* https://docs.github.com/en/enterprise-cloud@latest/admin/managing-accounts-and-repositories/managing-users-in-your-enterprise/roles-in-an-enterprise#enterprise-owners
"""
label: str = 'GitHubUser'
properties: GitHubUserNodeProperties = GitHubUserNodeProperties()
other_relationships: OtherRelationships = OtherRelationships(
[
GitHubUserMemberOfOrganizationRel(),
GitHubUserUnaffiliatedOrganizationRel(),
],
)
sub_resource_relationship = None

0 comments on commit 55f6f36

Please sign in to comment.