-
Notifications
You must be signed in to change notification settings - Fork 16
WIP: Add support for Secret Incidents API endpoints #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
a9fa044
872ac34
fad886c
162e297
d0f420a
d3d778e
640ad48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
from dataclasses import dataclass, field | ||
from datetime import datetime | ||
from typing import List, Optional, Type, Union, cast | ||
|
||
from marshmallow_dataclass import class_schema | ||
|
||
from pygitguardian.incident_models.constants import ( | ||
IncidentIgnoreReason, | ||
IncidentSeverity, | ||
IncidentStatus, | ||
IncidentTag, | ||
IncidentValidity, | ||
OccurrenceKind, | ||
OccurrencePresence, | ||
) | ||
from pygitguardian.models import Base, BaseSchema, FromDictMixin | ||
from pygitguardian.source_models import Source | ||
|
||
|
||
@dataclass | ||
class Detector(Base, FromDictMixin): | ||
name: str | ||
display_name: str | ||
nature: str | ||
family: str | ||
detector_group_name: str | ||
detector_group_display_name: str | ||
|
||
|
||
DetectorSchema = cast(Type[BaseSchema], class_schema(Detector, BaseSchema)) | ||
Detector.SCHEMA = DetectorSchema() | ||
|
||
|
||
@dataclass | ||
class Match(Base, FromDictMixin): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is already a |
||
name: str | ||
indice_start: int | ||
indice_end: int | ||
pre_line_start: Optional[int] | ||
pre_line_end: Optional[int] | ||
post_line_start: Optional[int] | ||
post_line_end: Optional[int] | ||
|
||
|
||
MatchSchema = cast(Type[BaseSchema], class_schema(Match, BaseSchema)) | ||
Match.SCHEMA = MatchSchema() | ||
|
||
|
||
@dataclass | ||
class Occurrence(Base, FromDictMixin): | ||
id: int | ||
incident_id: int | ||
kind: OccurrenceKind = field(metadata={"by_value": True}) | ||
sha: str | ||
source: Source | ||
author_name: str | ||
author_info: str | ||
date: datetime | ||
presence: OccurrencePresence = field(metadata={"by_value": True}) | ||
url: str | ||
matches: List[Match] | ||
filepath: str | ||
|
||
|
||
OccurrenceSchema = cast(Type[BaseSchema], class_schema(Occurrence, BaseSchema)) | ||
Occurrence.SCHEMA = OccurrenceSchema() | ||
|
||
|
||
@dataclass | ||
class Incident(Base, FromDictMixin): | ||
id: int | ||
date: datetime | ||
detector: Detector | ||
secret_hash: str | ||
gitguardian_url: str | ||
regression: bool | ||
status: IncidentStatus = field(metadata={"by_value": True}) | ||
assignee_email: Optional[str] | ||
occurrences_count: int | ||
occurrences: Optional[List[Occurrence]] | ||
ignore_reason: Optional[IncidentIgnoreReason] = field(metadata={"by_value": True}) | ||
ignored_at: Optional[datetime] | ||
secret_revoked: bool | ||
severity: IncidentSeverity = field(metadata={"by_value": True}) | ||
validity: IncidentValidity = field(metadata={"by_value": True}) | ||
resolved_at: Optional[datetime] | ||
share_url: Optional[str] | ||
tags: List[IncidentTag] = field(metadata={"by_value": True}) | ||
|
||
def __int__(self): | ||
return self.id | ||
Comment on lines
+90
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather not have such magic behavior, using |
||
|
||
|
||
IncidentSchema = cast(Type[BaseSchema], class_schema(Incident, BaseSchema)) | ||
Incident.SCHEMA = IncidentSchema() | ||
|
||
|
||
@dataclass | ||
class Link: | ||
url: str | ||
rel: str | ||
|
||
|
||
@dataclass | ||
class Links: | ||
next: Optional[Link] | ||
prev: Optional[Link] | ||
|
||
|
||
@dataclass | ||
class ListIncidentResult(Base, FromDictMixin): | ||
incidents: List[Incident] | ||
links: Optional[Links] = None | ||
|
||
|
||
ListIncidentResultSchema = cast( | ||
Type[BaseSchema], class_schema(ListIncidentResult, BaseSchema) | ||
) | ||
ListIncidentResult.SCHEMA = ListIncidentResultSchema() | ||
|
||
|
||
@dataclass | ||
class SharedIncidentDetails(Base, FromDictMixin): | ||
incident_id: int | ||
share_url: str | ||
feedback_collection: bool | ||
auto_healing: bool | ||
token: str | ||
expire_at: Optional[datetime] = None | ||
revoked_at: Optional[datetime] = None | ||
|
||
|
||
SharedIncidentDetailsSchema = cast( | ||
Type[BaseSchema], class_schema(SharedIncidentDetails, BaseSchema) | ||
) | ||
SharedIncidentDetails.SCHEMA = SharedIncidentDetailsSchema() | ||
|
||
IncidentIdOrIncident = Union[int, Incident] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from enum import auto | ||
|
||
from strenum import LowercaseStrEnum, MacroCaseStrEnum, SnakeCaseStrEnum, StrEnum | ||
|
||
|
||
class IncidentIgnoreReason(SnakeCaseStrEnum): | ||
TEST_CREDENTIAL = auto() | ||
FALSE_POSITIVE = auto() | ||
LOW_RISK = auto() | ||
|
||
|
||
class IncidentOrdering(StrEnum): | ||
DATE_ASC = "date" | ||
DATE_DESC = "-date" | ||
RESOLVED_AT_ASC = "resolved_at" | ||
RESOLVED_AT_DESC = "-resolved_at" | ||
IGNORED_AT_ASC = "ignored_at" | ||
IGNORED_AT_DESC = "-ignored_at" | ||
|
||
|
||
class IncidentPermission(LowercaseStrEnum): | ||
CAN_VIEW = auto() | ||
CAN_EDIT = auto() | ||
FULL_ACCESS = auto() | ||
|
||
|
||
class IncidentSeverity(SnakeCaseStrEnum): | ||
CRITICAL = auto() | ||
HIGH = auto() | ||
MEDIUM = auto() | ||
LOW = auto() | ||
INFO = auto() | ||
UNKNOWN = auto() | ||
|
||
|
||
class IncidentStatus(MacroCaseStrEnum): | ||
IGNORED = auto() | ||
TRIGGERED = auto() | ||
ASSIGNED = auto() | ||
RESOLVED = auto() | ||
|
||
|
||
class IncidentTag(MacroCaseStrEnum): | ||
DEFAULT_BRANCH = auto() | ||
FROM_HISTORICAL_SCAN = auto() | ||
IGNORED_IN_CHECK_RUN = auto() | ||
PUBLIC = auto() | ||
PUBLICLY_EXPOSED = auto() | ||
PUBLICLY_LEAKED = auto() | ||
REGRESSION = auto() | ||
SENSITIVE_FILE = auto() | ||
TEST_FILE = auto() | ||
|
||
|
||
class IncidentValidity(SnakeCaseStrEnum): | ||
VALID = auto() | ||
INVALID = auto() | ||
FAILED_TO_CHECK = auto() | ||
NO_CHECKER = auto() | ||
UNKNOWN = auto() | ||
|
||
|
||
class OccurrenceKind(LowercaseStrEnum): | ||
REALTIME = auto() | ||
HISTORICAL = auto() | ||
|
||
|
||
class OccurrencePresence(SnakeCaseStrEnum): | ||
present = auto() | ||
removed = auto() | ||
Comment on lines
+69
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you make these values upper-case, like the others? |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,8 +34,10 @@ def get_version() -> str: | |
install_requires=[ | ||
"marshmallow>=3.5, <4", | ||
"requests>=2, <3", | ||
"marshmallow-dataclass >=8.5.8, <8.6.0", | ||
"marshmallow-dataclass[enum,union] >=8.5.8, <8.6.0", | ||
"typing-extensions", | ||
"urllib3<2", | ||
"strenum", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you pin StrEnum to |
||
], | ||
include_package_data=True, | ||
zip_safe=True, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding StrEnum here is not required: non-dev dependencies only need to be in
setup.py
.