apimatic-semgrep-sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +28 -0
- data/README.md +205 -0
- data/bin/console +15 -0
- data/lib/semgrep_web_app/api_helper.rb +10 -0
- data/lib/semgrep_web_app/apis/base_api.rb +67 -0
- data/lib/semgrep_web_app/apis/deployments_service_api.rb +29 -0
- data/lib/semgrep_web_app/apis/findings_service_api.rb +107 -0
- data/lib/semgrep_web_app/apis/misc_service_api.rb +47 -0
- data/lib/semgrep_web_app/apis/policies_service_api.rb +97 -0
- data/lib/semgrep_web_app/apis/projects_service_api.rb +238 -0
- data/lib/semgrep_web_app/apis/scans_service_api.rb +65 -0
- data/lib/semgrep_web_app/apis/secrets_service_api.rb +55 -0
- data/lib/semgrep_web_app/apis/supply_chain_service_api.rb +154 -0
- data/lib/semgrep_web_app/apis/ticketing_service_api.rb +144 -0
- data/lib/semgrep_web_app/apis/triage_service_api.rb +43 -0
- data/lib/semgrep_web_app/client.rb +136 -0
- data/lib/semgrep_web_app/configuration.rb +178 -0
- data/lib/semgrep_web_app/exceptions/api_exception.rb +21 -0
- data/lib/semgrep_web_app/http/api_response.rb +19 -0
- data/lib/semgrep_web_app/http/auth/semgrep_admin_jwt.rb +53 -0
- data/lib/semgrep_web_app/http/auth/semgrep_jwt.rb +53 -0
- data/lib/semgrep_web_app/http/auth/semgrep_web_token.rb +53 -0
- data/lib/semgrep_web_app/http/http_call_back.rb +10 -0
- data/lib/semgrep_web_app/http/http_method_enum.rb +10 -0
- data/lib/semgrep_web_app/http/http_request.rb +10 -0
- data/lib/semgrep_web_app/http/http_response.rb +10 -0
- data/lib/semgrep_web_app/http/proxy_settings.rb +22 -0
- data/lib/semgrep_web_app/logging/configuration/api_logging_configuration.rb +186 -0
- data/lib/semgrep_web_app/logging/sdk_logger.rb +17 -0
- data/lib/semgrep_web_app/models/add_project_tags_request.rb +96 -0
- data/lib/semgrep_web_app/models/add_project_tags_response.rb +73 -0
- data/lib/semgrep_web_app/models/ai_powered_scan_finding.rb +426 -0
- data/lib/semgrep_web_app/models/ai_sast_findings.rb +85 -0
- data/lib/semgrep_web_app/models/api_v1_deployments_findings_response.rb +87 -0
- data/lib/semgrep_web_app/models/assistant.rb +127 -0
- data/lib/semgrep_web_app/models/autofix.rb +98 -0
- data/lib/semgrep_web_app/models/autotriage.rb +98 -0
- data/lib/semgrep_web_app/models/autotriage_verdict.rb +36 -0
- data/lib/semgrep_web_app/models/autotriage_verdict2.rb +38 -0
- data/lib/semgrep_web_app/models/base_model.rb +110 -0
- data/lib/semgrep_web_app/models/bulk_triage_request.rb +393 -0
- data/lib/semgrep_web_app/models/bulk_triage_response.rb +83 -0
- data/lib/semgrep_web_app/models/click_to_fix_failure.rb +95 -0
- data/lib/semgrep_web_app/models/click_to_fix_pr.rb +95 -0
- data/lib/semgrep_web_app/models/click_to_fix_pr_state.rb +38 -0
- data/lib/semgrep_web_app/models/component.rb +95 -0
- data/lib/semgrep_web_app/models/confidence.rb +42 -0
- data/lib/semgrep_web_app/models/confidence1.rb +40 -0
- data/lib/semgrep_web_app/models/confidence2.rb +40 -0
- data/lib/semgrep_web_app/models/confidence3.rb +40 -0
- data/lib/semgrep_web_app/models/confidence7.rb +41 -0
- data/lib/semgrep_web_app/models/confidence8.rb +42 -0
- data/lib/semgrep_web_app/models/create_sbom_export_request.rb +176 -0
- data/lib/semgrep_web_app/models/create_sbom_export_response.rb +74 -0
- data/lib/semgrep_web_app/models/create_ticket_request.rb +393 -0
- data/lib/semgrep_web_app/models/cyclonedx_version.rb +48 -0
- data/lib/semgrep_web_app/models/delete_project_response.rb +74 -0
- data/lib/semgrep_web_app/models/delete_project_tags_response.rb +73 -0
- data/lib/semgrep_web_app/models/deployment.rb +102 -0
- data/lib/semgrep_web_app/models/ecosystem.rb +91 -0
- data/lib/semgrep_web_app/models/ecosystem1.rb +92 -0
- data/lib/semgrep_web_app/models/ecosystem2.rb +76 -0
- data/lib/semgrep_web_app/models/endpoint_reference.rb +72 -0
- data/lib/semgrep_web_app/models/epss_probability.rb +45 -0
- data/lib/semgrep_web_app/models/epss_score.rb +95 -0
- data/lib/semgrep_web_app/models/exposures.rb +50 -0
- data/lib/semgrep_web_app/models/exposures2.rb +51 -0
- data/lib/semgrep_web_app/models/external_ticket.rb +116 -0
- data/lib/semgrep_web_app/models/finding_location.rb +126 -0
- data/lib/semgrep_web_app/models/finding_repository.rb +95 -0
- data/lib/semgrep_web_app/models/finding_rule.rb +158 -0
- data/lib/semgrep_web_app/models/fix_recommendation.rb +95 -0
- data/lib/semgrep_web_app/models/float_range.rb +85 -0
- data/lib/semgrep_web_app/models/format.rb +27 -0
- data/lib/semgrep_web_app/models/found_dependency.rb +128 -0
- data/lib/semgrep_web_app/models/get_project_response.rb +73 -0
- data/lib/semgrep_web_app/models/get_sbom_export_response.rb +100 -0
- data/lib/semgrep_web_app/models/guidance.rb +98 -0
- data/lib/semgrep_web_app/models/issue_type.rb +40 -0
- data/lib/semgrep_web_app/models/issue_type1.rb +40 -0
- data/lib/semgrep_web_app/models/issue_type2.rb +42 -0
- data/lib/semgrep_web_app/models/license_policy_settings.rb +42 -0
- data/lib/semgrep_web_app/models/link_ticket_request.rb +93 -0
- data/lib/semgrep_web_app/models/list_dependencies_request.rb +108 -0
- data/lib/semgrep_web_app/models/list_dependencies_response.rb +102 -0
- data/lib/semgrep_web_app/models/list_findings_response.rb +100 -0
- data/lib/semgrep_web_app/models/list_lockfiles_for_dependencies_request.rb +118 -0
- data/lib/semgrep_web_app/models/list_lockfiles_for_dependencies_response.rb +103 -0
- data/lib/semgrep_web_app/models/list_project.rb +145 -0
- data/lib/semgrep_web_app/models/list_projects_response.rb +82 -0
- data/lib/semgrep_web_app/models/list_repositories_for_dependencies_request.rb +107 -0
- data/lib/semgrep_web_app/models/list_repositories_for_dependencies_response.rb +103 -0
- data/lib/semgrep_web_app/models/managed_scan_config.rb +85 -0
- data/lib/semgrep_web_app/models/metadata_component_type.rb +101 -0
- data/lib/semgrep_web_app/models/mode.rb +48 -0
- data/lib/semgrep_web_app/models/new_triage_reason.rb +48 -0
- data/lib/semgrep_web_app/models/new_triage_state.rb +48 -0
- data/lib/semgrep_web_app/models/policy.rb +118 -0
- data/lib/semgrep_web_app/models/policy_mode.rb +48 -0
- data/lib/semgrep_web_app/models/policy_mode1.rb +40 -0
- data/lib/semgrep_web_app/models/policy_mode3.rb +51 -0
- data/lib/semgrep_web_app/models/policy_reference.rb +105 -0
- data/lib/semgrep_web_app/models/product_type.rb +38 -0
- data/lib/semgrep_web_app/models/products.rb +46 -0
- data/lib/semgrep_web_app/models/project.rb +157 -0
- data/lib/semgrep_web_app/models/protos_ai_v1_autotriage.rb +154 -0
- data/lib/semgrep_web_app/models/protos_ai_v1_autotriage_feedback.rb +98 -0
- data/lib/semgrep_web_app/models/protos_common_v1_review_comment.rb +90 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_create_ticket_response.rb +123 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_create_ticket_response_ticket_creation_failed.rb +85 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_create_ticket_response_ticket_creation_skipped.rb +85 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_create_ticket_response_ticket_creation_success.rb +106 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_delete_ticket_response.rb +76 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_diff_scan.rb +75 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_full_scan.rb +75 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_get_bootstrap_sms_vpc_response.rb +130 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_get_scan_response.rb +168 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_get_scan_response_scan_meta.rb +256 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_link_ticket_response.rb +119 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_list_deployments_response.rb +85 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_list_policies_response.rb +84 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_list_policy_rules_response.rb +104 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_list_secrets_path_response.rb +104 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_search_scans_response.rb +94 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_unlink_ticket_response.rb +77 -0
- data/lib/semgrep_web_app/models/protos_openapi_v1_update_policy_response.rb +88 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_code_location.rb +144 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_dependency.rb +87 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_dependency_filter.rb +199 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_found_dependency.rb +174 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_lockfile_dependency_summary.rb +87 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_package_filter.rb +124 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_repository_dependency_summary.rb +111 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_sbom_format_version.rb +109 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_sbom_metadata_contact.rb +95 -0
- data/lib/semgrep_web_app/models/protos_sca_v1_sbom_metadata_supplier.rb +95 -0
- data/lib/semgrep_web_app/models/protos_scan_v1_scan_findings_counts.rb +105 -0
- data/lib/semgrep_web_app/models/protos_scan_v1_scan_public.rb +228 -0
- data/lib/semgrep_web_app/models/protos_secrets_v1_historical_info.rb +116 -0
- data/lib/semgrep_web_app/models/protos_secrets_v1_secrets_finding.rb +320 -0
- data/lib/semgrep_web_app/models/protos_secrets_v1_secrets_finding_repository.rb +121 -0
- data/lib/semgrep_web_app/models/protos_ticketing_v1_external_ticket.rb +106 -0
- data/lib/semgrep_web_app/models/rating.rb +38 -0
- data/lib/semgrep_web_app/models/reachability.rb +48 -0
- data/lib/semgrep_web_app/models/repository_visibility.rb +40 -0
- data/lib/semgrep_web_app/models/review_comment.rb +100 -0
- data/lib/semgrep_web_app/models/risk.rb +40 -0
- data/lib/semgrep_web_app/models/rule.rb +292 -0
- data/lib/semgrep_web_app/models/rule_explanation.rb +98 -0
- data/lib/semgrep_web_app/models/sast_finding.rb +426 -0
- data/lib/semgrep_web_app/models/sast_findings.rb +84 -0
- data/lib/semgrep_web_app/models/sbom_output_format.rb +37 -0
- data/lib/semgrep_web_app/models/sca_finding.rb +458 -0
- data/lib/semgrep_web_app/models/sca_findings.rb +85 -0
- data/lib/semgrep_web_app/models/scm_type.rb +70 -0
- data/lib/semgrep_web_app/models/search_scans_request.rb +202 -0
- data/lib/semgrep_web_app/models/severities.rb +44 -0
- data/lib/semgrep_web_app/models/severities2.rb +45 -0
- data/lib/semgrep_web_app/models/severity.rb +46 -0
- data/lib/semgrep_web_app/models/severity1.rb +45 -0
- data/lib/semgrep_web_app/models/severity4.rb +46 -0
- data/lib/semgrep_web_app/models/severity5.rb +48 -0
- data/lib/semgrep_web_app/models/source.rb +42 -0
- data/lib/semgrep_web_app/models/state.rb +42 -0
- data/lib/semgrep_web_app/models/status.rb +55 -0
- data/lib/semgrep_web_app/models/status1.rb +52 -0
- data/lib/semgrep_web_app/models/status3.rb +44 -0
- data/lib/semgrep_web_app/models/status6.rb +55 -0
- data/lib/semgrep_web_app/models/status7.rb +59 -0
- data/lib/semgrep_web_app/models/status8.rb +61 -0
- data/lib/semgrep_web_app/models/status9.rb +55 -0
- data/lib/semgrep_web_app/models/statuses.rb +63 -0
- data/lib/semgrep_web_app/models/toggle_project_managed_scan_request.rb +108 -0
- data/lib/semgrep_web_app/models/toggle_project_managed_scan_response.rb +73 -0
- data/lib/semgrep_web_app/models/transitivities.rb +40 -0
- data/lib/semgrep_web_app/models/transitivities2.rb +42 -0
- data/lib/semgrep_web_app/models/transitivity.rb +41 -0
- data/lib/semgrep_web_app/models/transitivity1.rb +42 -0
- data/lib/semgrep_web_app/models/transitivity2.rb +40 -0
- data/lib/semgrep_web_app/models/triage_reason.rb +48 -0
- data/lib/semgrep_web_app/models/triage_reasons.rb +48 -0
- data/lib/semgrep_web_app/models/triage_reasons2.rb +50 -0
- data/lib/semgrep_web_app/models/triage_state.rb +54 -0
- data/lib/semgrep_web_app/models/unlink_ticket_request.rb +83 -0
- data/lib/semgrep_web_app/models/update_policy_request.rb +113 -0
- data/lib/semgrep_web_app/models/update_project_request.rb +121 -0
- data/lib/semgrep_web_app/models/update_project_response.rb +73 -0
- data/lib/semgrep_web_app/models/usage.rb +99 -0
- data/lib/semgrep_web_app/models/validation_state.rb +45 -0
- data/lib/semgrep_web_app/models/validation_state2.rb +47 -0
- data/lib/semgrep_web_app/models/validation_state3.rb +48 -0
- data/lib/semgrep_web_app/models/verdict.rb +41 -0
- data/lib/semgrep_web_app/models/verdict1.rb +38 -0
- data/lib/semgrep_web_app/models/visibility.rb +42 -0
- data/lib/semgrep_web_app/utilities/date_time_helper.rb +11 -0
- data/lib/semgrep_web_app/utilities/file_wrapper.rb +28 -0
- data/lib/semgrep_web_app/utilities/union_type_lookup.rb +34 -0
- data/lib/semgrep_web_app.rb +245 -0
- metadata +283 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# Indicates whether the dependency is direct or transitive
|
|
8
|
+
class Transitivity2
|
|
9
|
+
TRANSITIVITY2 = [
|
|
10
|
+
# TODO: Write general description for DIRECT
|
|
11
|
+
DIRECT = 'direct'.freeze,
|
|
12
|
+
|
|
13
|
+
# TODO: Write general description for TRANSITIVE
|
|
14
|
+
TRANSITIVE = 'transitive'.freeze,
|
|
15
|
+
|
|
16
|
+
# TODO: Write general description for UNKNOWN
|
|
17
|
+
UNKNOWN = 'unknown'.freeze
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
def self.validate(value)
|
|
21
|
+
return false if value.nil?
|
|
22
|
+
|
|
23
|
+
TRANSITIVITY2.include?(value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.from_value(value, default_value = DIRECT)
|
|
27
|
+
return default_value if value.nil?
|
|
28
|
+
|
|
29
|
+
str = value.to_s.strip
|
|
30
|
+
|
|
31
|
+
case str.downcase
|
|
32
|
+
when 'direct' then DIRECT
|
|
33
|
+
when 'transitive' then TRANSITIVE
|
|
34
|
+
when 'unknown' then UNKNOWN
|
|
35
|
+
else
|
|
36
|
+
default_value
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# Reason provided when this issue was triaged
|
|
8
|
+
class TriageReason
|
|
9
|
+
TRIAGE_REASON = [
|
|
10
|
+
# TODO: Write general description for ACCEPTABLE_RISK
|
|
11
|
+
ACCEPTABLE_RISK = 'acceptable_risk'.freeze,
|
|
12
|
+
|
|
13
|
+
# TODO: Write general description for FALSE_POSITIVE
|
|
14
|
+
FALSE_POSITIVE = 'false_positive'.freeze,
|
|
15
|
+
|
|
16
|
+
# TODO: Write general description for NO_TIME
|
|
17
|
+
NO_TIME = 'no_time'.freeze,
|
|
18
|
+
|
|
19
|
+
# TODO: Write general description for NO_TRIAGE_REASON
|
|
20
|
+
NO_TRIAGE_REASON = 'no_triage_reason'.freeze,
|
|
21
|
+
|
|
22
|
+
# TODO: Write general description for DUPLICATE
|
|
23
|
+
DUPLICATE = 'duplicate'.freeze
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
26
|
+
def self.validate(value)
|
|
27
|
+
return false if value.nil?
|
|
28
|
+
|
|
29
|
+
TRIAGE_REASON.include?(value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.from_value(value, default_value = ACCEPTABLE_RISK)
|
|
33
|
+
return default_value if value.nil?
|
|
34
|
+
|
|
35
|
+
str = value.to_s.strip
|
|
36
|
+
|
|
37
|
+
case str.downcase
|
|
38
|
+
when 'acceptable_risk' then ACCEPTABLE_RISK
|
|
39
|
+
when 'false_positive' then FALSE_POSITIVE
|
|
40
|
+
when 'no_time' then NO_TIME
|
|
41
|
+
when 'no_triage_reason' then NO_TRIAGE_REASON
|
|
42
|
+
when 'duplicate' then DUPLICATE
|
|
43
|
+
else
|
|
44
|
+
default_value
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# List of triage reasons to filter by
|
|
8
|
+
class TriageReasons
|
|
9
|
+
TRIAGE_REASONS = [
|
|
10
|
+
# TODO: Write general description for ACCEPTABLE_RISK
|
|
11
|
+
ACCEPTABLE_RISK = 'acceptable_risk'.freeze,
|
|
12
|
+
|
|
13
|
+
# TODO: Write general description for FALSE_POSITIVE
|
|
14
|
+
FALSE_POSITIVE = 'false_positive'.freeze,
|
|
15
|
+
|
|
16
|
+
# TODO: Write general description for NO_TIME
|
|
17
|
+
NO_TIME = 'no_time'.freeze,
|
|
18
|
+
|
|
19
|
+
# TODO: Write general description for NO_TRIAGE_REASON
|
|
20
|
+
NO_TRIAGE_REASON = 'no_triage_reason'.freeze,
|
|
21
|
+
|
|
22
|
+
# TODO: Write general description for DUPLICATE
|
|
23
|
+
DUPLICATE = 'duplicate'.freeze
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
26
|
+
def self.validate(value)
|
|
27
|
+
return false if value.nil?
|
|
28
|
+
|
|
29
|
+
TRIAGE_REASONS.include?(value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.from_value(value, default_value = ACCEPTABLE_RISK)
|
|
33
|
+
return default_value if value.nil?
|
|
34
|
+
|
|
35
|
+
str = value.to_s.strip
|
|
36
|
+
|
|
37
|
+
case str.downcase
|
|
38
|
+
when 'acceptable_risk' then ACCEPTABLE_RISK
|
|
39
|
+
when 'false_positive' then FALSE_POSITIVE
|
|
40
|
+
when 'no_time' then NO_TIME
|
|
41
|
+
when 'no_triage_reason' then NO_TRIAGE_REASON
|
|
42
|
+
when 'duplicate' then DUPLICATE
|
|
43
|
+
else
|
|
44
|
+
default_value
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# Which triage reasons do you want to include? If not specified, includes all.
|
|
8
|
+
# This filter is applicable when `status` is `ignored`. Valid values:
|
|
9
|
+
# acceptable_risk, false_positive, no_time, no_triage_reason, duplicate
|
|
10
|
+
class TriageReasons2
|
|
11
|
+
TRIAGE_REASONS2 = [
|
|
12
|
+
# TODO: Write general description for ACCEPTABLE_RISK
|
|
13
|
+
ACCEPTABLE_RISK = 'acceptable_risk'.freeze,
|
|
14
|
+
|
|
15
|
+
# TODO: Write general description for FALSE_POSITIVE
|
|
16
|
+
FALSE_POSITIVE = 'false_positive'.freeze,
|
|
17
|
+
|
|
18
|
+
# TODO: Write general description for NO_TIME
|
|
19
|
+
NO_TIME = 'no_time'.freeze,
|
|
20
|
+
|
|
21
|
+
# TODO: Write general description for NO_TRIAGE_REASON
|
|
22
|
+
NO_TRIAGE_REASON = 'no_triage_reason'.freeze,
|
|
23
|
+
|
|
24
|
+
# TODO: Write general description for DUPLICATE
|
|
25
|
+
DUPLICATE = 'duplicate'.freeze
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
def self.validate(value)
|
|
29
|
+
return false if value.nil?
|
|
30
|
+
|
|
31
|
+
TRIAGE_REASONS2.include?(value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.from_value(value, default_value = ACCEPTABLE_RISK)
|
|
35
|
+
return default_value if value.nil?
|
|
36
|
+
|
|
37
|
+
str = value.to_s.strip
|
|
38
|
+
|
|
39
|
+
case str.downcase
|
|
40
|
+
when 'acceptable_risk' then ACCEPTABLE_RISK
|
|
41
|
+
when 'false_positive' then FALSE_POSITIVE
|
|
42
|
+
when 'no_time' then NO_TIME
|
|
43
|
+
when 'no_triage_reason' then NO_TRIAGE_REASON
|
|
44
|
+
when 'duplicate' then DUPLICATE
|
|
45
|
+
else
|
|
46
|
+
default_value
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# The finding's triage state. Note: "reviewing" and "fixing" are only in
|
|
8
|
+
# private beta. Set by the user and used along with state to generate the
|
|
9
|
+
# final "status" viewable in the UI
|
|
10
|
+
class TriageState
|
|
11
|
+
TRIAGE_STATE = [
|
|
12
|
+
# TODO: Write general description for UNTRIAGED
|
|
13
|
+
UNTRIAGED = 'untriaged'.freeze,
|
|
14
|
+
|
|
15
|
+
# TODO: Write general description for IGNORED
|
|
16
|
+
IGNORED = 'ignored'.freeze,
|
|
17
|
+
|
|
18
|
+
# TODO: Write general description for REOPENED
|
|
19
|
+
REOPENED = 'reopened'.freeze,
|
|
20
|
+
|
|
21
|
+
# TODO: Write general description for REVIEWING
|
|
22
|
+
REVIEWING = 'reviewing'.freeze,
|
|
23
|
+
|
|
24
|
+
# TODO: Write general description for FIXING
|
|
25
|
+
FIXING = 'fixing'.freeze,
|
|
26
|
+
|
|
27
|
+
# TODO: Write general description for PROVISIONALLY_IGNORED
|
|
28
|
+
PROVISIONALLY_IGNORED = 'provisionally_ignored'.freeze
|
|
29
|
+
].freeze
|
|
30
|
+
|
|
31
|
+
def self.validate(value)
|
|
32
|
+
return false if value.nil?
|
|
33
|
+
|
|
34
|
+
TRIAGE_STATE.include?(value)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.from_value(value, default_value = UNTRIAGED)
|
|
38
|
+
return default_value if value.nil?
|
|
39
|
+
|
|
40
|
+
str = value.to_s.strip
|
|
41
|
+
|
|
42
|
+
case str.downcase
|
|
43
|
+
when 'untriaged' then UNTRIAGED
|
|
44
|
+
when 'ignored' then IGNORED
|
|
45
|
+
when 'reopened' then REOPENED
|
|
46
|
+
when 'reviewing' then REVIEWING
|
|
47
|
+
when 'fixing' then FIXING
|
|
48
|
+
when 'provisionally_ignored' then PROVISIONALLY_IGNORED
|
|
49
|
+
else
|
|
50
|
+
default_value
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# Unlink ticket request
|
|
8
|
+
class UnlinkTicketRequest < BaseModel
|
|
9
|
+
SKIP = Object.new
|
|
10
|
+
private_constant :SKIP
|
|
11
|
+
|
|
12
|
+
# Deployment ID. Can be found at /deployments, or in your Settings in the
|
|
13
|
+
# web UI.
|
|
14
|
+
# @return [String]
|
|
15
|
+
attr_accessor :deployment_id
|
|
16
|
+
|
|
17
|
+
# An array of Semgrep finding IDs to unlink tickets from.
|
|
18
|
+
# @return [Array[String]]
|
|
19
|
+
attr_accessor :issue_ids
|
|
20
|
+
|
|
21
|
+
# A mapping from model property names to API property names.
|
|
22
|
+
def self.names
|
|
23
|
+
@_hash = {} if @_hash.nil?
|
|
24
|
+
@_hash['deployment_id'] = 'deploymentId'
|
|
25
|
+
@_hash['issue_ids'] = 'issue_ids'
|
|
26
|
+
@_hash
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# An array for optional fields
|
|
30
|
+
def self.optionals
|
|
31
|
+
[]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# An array for nullable fields
|
|
35
|
+
def self.nullables
|
|
36
|
+
[]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def initialize(deployment_id:, issue_ids:, additional_properties: nil)
|
|
40
|
+
# Add additional model properties to the instance
|
|
41
|
+
additional_properties = {} if additional_properties.nil?
|
|
42
|
+
|
|
43
|
+
@deployment_id = deployment_id
|
|
44
|
+
@issue_ids = issue_ids
|
|
45
|
+
@additional_properties = additional_properties
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Creates an instance of the object from a hash.
|
|
49
|
+
def self.from_hash(hash)
|
|
50
|
+
return nil unless hash
|
|
51
|
+
|
|
52
|
+
# Extract variables from the hash.
|
|
53
|
+
deployment_id = hash.key?('deploymentId') ? hash['deploymentId'] : nil
|
|
54
|
+
issue_ids = hash.key?('issue_ids') ? hash['issue_ids'] : nil
|
|
55
|
+
|
|
56
|
+
# Create a new hash for additional properties, removing known properties.
|
|
57
|
+
new_hash = hash.reject { |k, _| names.value?(k) }
|
|
58
|
+
|
|
59
|
+
additional_properties = APIHelper.get_additional_properties(
|
|
60
|
+
new_hash, proc { |value| value }
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Create object from extracted values.
|
|
64
|
+
UnlinkTicketRequest.new(deployment_id: deployment_id,
|
|
65
|
+
issue_ids: issue_ids,
|
|
66
|
+
additional_properties: additional_properties)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Provides a human-readable string representation of the object.
|
|
70
|
+
def to_s
|
|
71
|
+
class_name = self.class.name.split('::').last
|
|
72
|
+
"<#{class_name} deployment_id: #{@deployment_id}, issue_ids: #{@issue_ids},"\
|
|
73
|
+
" additional_properties: #{@additional_properties}>"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Provides a debugging-friendly string with detailed object information.
|
|
77
|
+
def inspect
|
|
78
|
+
class_name = self.class.name.split('::').last
|
|
79
|
+
"<#{class_name} deployment_id: #{@deployment_id.inspect}, issue_ids: #{@issue_ids.inspect},"\
|
|
80
|
+
" additional_properties: #{@additional_properties}>"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# UpdatePolicyRequest Model.
|
|
8
|
+
class UpdatePolicyRequest < BaseModel
|
|
9
|
+
SKIP = Object.new
|
|
10
|
+
private_constant :SKIP
|
|
11
|
+
|
|
12
|
+
# Deployment ID (numeric). Example: `123`. Can be found at `/deployments`,
|
|
13
|
+
# or in your Settings in the web UI.
|
|
14
|
+
# @return [String]
|
|
15
|
+
attr_accessor :deployment_id
|
|
16
|
+
|
|
17
|
+
# Policy ID (numeric). Example: `456`. Can be found at
|
|
18
|
+
# `/deployments/{deploymentId}/policies`.
|
|
19
|
+
# @return [String]
|
|
20
|
+
attr_accessor :policy_id
|
|
21
|
+
|
|
22
|
+
# New policy mode to set for the Rule.
|
|
23
|
+
# - MODE_MONITOR: Monitor mode, silently report findings
|
|
24
|
+
# - MODE_COMMENT: Comment mode, leaves PR comments but does not block
|
|
25
|
+
# - MODE_BLOCK: Block mode, leaves PR comments and blocks PR
|
|
26
|
+
# - MODE_DISABLED: Disabled mode, not active
|
|
27
|
+
# | value | description |
|
|
28
|
+
# |-------|---------------|
|
|
29
|
+
# | MODE_MONITOR | Monitor mode, silently report findings |
|
|
30
|
+
# | MODE_COMMENT | Comment mode, leaves PR comments but does not block |
|
|
31
|
+
# | MODE_BLOCK | Block mode, leaves PR comments and blocks PR |
|
|
32
|
+
# | MODE_DISABLED | Disabled mode, not active |
|
|
33
|
+
# @return [PolicyMode3]
|
|
34
|
+
attr_accessor :policy_mode
|
|
35
|
+
|
|
36
|
+
# Full path of the Rule.
|
|
37
|
+
# @return [String]
|
|
38
|
+
attr_accessor :rule_path
|
|
39
|
+
|
|
40
|
+
# A mapping from model property names to API property names.
|
|
41
|
+
def self.names
|
|
42
|
+
@_hash = {} if @_hash.nil?
|
|
43
|
+
@_hash['deployment_id'] = 'deploymentId'
|
|
44
|
+
@_hash['policy_id'] = 'policyId'
|
|
45
|
+
@_hash['policy_mode'] = 'policyMode'
|
|
46
|
+
@_hash['rule_path'] = 'rulePath'
|
|
47
|
+
@_hash
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# An array for optional fields
|
|
51
|
+
def self.optionals
|
|
52
|
+
[]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# An array for nullable fields
|
|
56
|
+
def self.nullables
|
|
57
|
+
[]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def initialize(deployment_id:, policy_id:, policy_mode:, rule_path:,
|
|
61
|
+
additional_properties: nil)
|
|
62
|
+
# Add additional model properties to the instance
|
|
63
|
+
additional_properties = {} if additional_properties.nil?
|
|
64
|
+
|
|
65
|
+
@deployment_id = deployment_id
|
|
66
|
+
@policy_id = policy_id
|
|
67
|
+
@policy_mode = policy_mode
|
|
68
|
+
@rule_path = rule_path
|
|
69
|
+
@additional_properties = additional_properties
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Creates an instance of the object from a hash.
|
|
73
|
+
def self.from_hash(hash)
|
|
74
|
+
return nil unless hash
|
|
75
|
+
|
|
76
|
+
# Extract variables from the hash.
|
|
77
|
+
deployment_id = hash.key?('deploymentId') ? hash['deploymentId'] : nil
|
|
78
|
+
policy_id = hash.key?('policyId') ? hash['policyId'] : nil
|
|
79
|
+
policy_mode = hash.key?('policyMode') ? hash['policyMode'] : nil
|
|
80
|
+
rule_path = hash.key?('rulePath') ? hash['rulePath'] : nil
|
|
81
|
+
|
|
82
|
+
# Create a new hash for additional properties, removing known properties.
|
|
83
|
+
new_hash = hash.reject { |k, _| names.value?(k) }
|
|
84
|
+
|
|
85
|
+
additional_properties = APIHelper.get_additional_properties(
|
|
86
|
+
new_hash, proc { |value| value }
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Create object from extracted values.
|
|
90
|
+
UpdatePolicyRequest.new(deployment_id: deployment_id,
|
|
91
|
+
policy_id: policy_id,
|
|
92
|
+
policy_mode: policy_mode,
|
|
93
|
+
rule_path: rule_path,
|
|
94
|
+
additional_properties: additional_properties)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Provides a human-readable string representation of the object.
|
|
98
|
+
def to_s
|
|
99
|
+
class_name = self.class.name.split('::').last
|
|
100
|
+
"<#{class_name} deployment_id: #{@deployment_id}, policy_id: #{@policy_id}, policy_mode:"\
|
|
101
|
+
" #{@policy_mode}, rule_path: #{@rule_path}, additional_properties:"\
|
|
102
|
+
" #{@additional_properties}>"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Provides a debugging-friendly string with detailed object information.
|
|
106
|
+
def inspect
|
|
107
|
+
class_name = self.class.name.split('::').last
|
|
108
|
+
"<#{class_name} deployment_id: #{@deployment_id.inspect}, policy_id: #{@policy_id.inspect},"\
|
|
109
|
+
" policy_mode: #{@policy_mode.inspect}, rule_path: #{@rule_path.inspect},"\
|
|
110
|
+
" additional_properties: #{@additional_properties}>"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# UpdateProjectRequest Model.
|
|
8
|
+
class UpdateProjectRequest < BaseModel
|
|
9
|
+
SKIP = Object.new
|
|
10
|
+
private_constant :SKIP
|
|
11
|
+
|
|
12
|
+
# Slug of the deployment name. Can be found at `/deployments`, or in your
|
|
13
|
+
# Settings in the web UI.
|
|
14
|
+
# @return [String]
|
|
15
|
+
attr_accessor :deployment_slug
|
|
16
|
+
|
|
17
|
+
# [Beta] Configuration of Semgrep Managed Scans for the project, if
|
|
18
|
+
# relevant.
|
|
19
|
+
# @return [ManagedScanConfig]
|
|
20
|
+
attr_accessor :managed_scan_config
|
|
21
|
+
|
|
22
|
+
# The full name of the branch you would like to set as primary. Use "None"
|
|
23
|
+
# if default_branch is known and you wish to set primary to always be the
|
|
24
|
+
# default branch.
|
|
25
|
+
# @return [String]
|
|
26
|
+
attr_accessor :primary_branch
|
|
27
|
+
|
|
28
|
+
# Name of the project, typically the repository formatted as a path.
|
|
29
|
+
# @return [String]
|
|
30
|
+
attr_accessor :project_name
|
|
31
|
+
|
|
32
|
+
# Tags associated to this project.
|
|
33
|
+
# @return [Array[String]]
|
|
34
|
+
attr_accessor :tags
|
|
35
|
+
|
|
36
|
+
# A mapping from model property names to API property names.
|
|
37
|
+
def self.names
|
|
38
|
+
@_hash = {} if @_hash.nil?
|
|
39
|
+
@_hash['deployment_slug'] = 'deploymentSlug'
|
|
40
|
+
@_hash['managed_scan_config'] = 'managed_scan_config'
|
|
41
|
+
@_hash['primary_branch'] = 'primary_branch'
|
|
42
|
+
@_hash['project_name'] = 'projectName'
|
|
43
|
+
@_hash['tags'] = 'tags'
|
|
44
|
+
@_hash
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# An array for optional fields
|
|
48
|
+
def self.optionals
|
|
49
|
+
%w[
|
|
50
|
+
managed_scan_config
|
|
51
|
+
primary_branch
|
|
52
|
+
tags
|
|
53
|
+
]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# An array for nullable fields
|
|
57
|
+
def self.nullables
|
|
58
|
+
[]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize(deployment_slug:, project_name:, managed_scan_config: SKIP,
|
|
62
|
+
primary_branch: SKIP, tags: SKIP, additional_properties: nil)
|
|
63
|
+
# Add additional model properties to the instance
|
|
64
|
+
additional_properties = {} if additional_properties.nil?
|
|
65
|
+
|
|
66
|
+
@deployment_slug = deployment_slug
|
|
67
|
+
@managed_scan_config = managed_scan_config unless managed_scan_config == SKIP
|
|
68
|
+
@primary_branch = primary_branch unless primary_branch == SKIP
|
|
69
|
+
@project_name = project_name
|
|
70
|
+
@tags = tags unless tags == SKIP
|
|
71
|
+
@additional_properties = additional_properties
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Creates an instance of the object from a hash.
|
|
75
|
+
def self.from_hash(hash)
|
|
76
|
+
return nil unless hash
|
|
77
|
+
|
|
78
|
+
# Extract variables from the hash.
|
|
79
|
+
deployment_slug =
|
|
80
|
+
hash.key?('deploymentSlug') ? hash['deploymentSlug'] : nil
|
|
81
|
+
project_name = hash.key?('projectName') ? hash['projectName'] : nil
|
|
82
|
+
managed_scan_config = ManagedScanConfig.from_hash(hash['managed_scan_config']) if
|
|
83
|
+
hash['managed_scan_config']
|
|
84
|
+
primary_branch =
|
|
85
|
+
hash.key?('primary_branch') ? hash['primary_branch'] : SKIP
|
|
86
|
+
tags = hash.key?('tags') ? hash['tags'] : SKIP
|
|
87
|
+
|
|
88
|
+
# Create a new hash for additional properties, removing known properties.
|
|
89
|
+
new_hash = hash.reject { |k, _| names.value?(k) }
|
|
90
|
+
|
|
91
|
+
additional_properties = APIHelper.get_additional_properties(
|
|
92
|
+
new_hash, proc { |value| value }
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Create object from extracted values.
|
|
96
|
+
UpdateProjectRequest.new(deployment_slug: deployment_slug,
|
|
97
|
+
project_name: project_name,
|
|
98
|
+
managed_scan_config: managed_scan_config,
|
|
99
|
+
primary_branch: primary_branch,
|
|
100
|
+
tags: tags,
|
|
101
|
+
additional_properties: additional_properties)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Provides a human-readable string representation of the object.
|
|
105
|
+
def to_s
|
|
106
|
+
class_name = self.class.name.split('::').last
|
|
107
|
+
"<#{class_name} deployment_slug: #{@deployment_slug}, managed_scan_config:"\
|
|
108
|
+
" #{@managed_scan_config}, primary_branch: #{@primary_branch}, project_name:"\
|
|
109
|
+
" #{@project_name}, tags: #{@tags}, additional_properties: #{@additional_properties}>"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Provides a debugging-friendly string with detailed object information.
|
|
113
|
+
def inspect
|
|
114
|
+
class_name = self.class.name.split('::').last
|
|
115
|
+
"<#{class_name} deployment_slug: #{@deployment_slug.inspect}, managed_scan_config:"\
|
|
116
|
+
" #{@managed_scan_config.inspect}, primary_branch: #{@primary_branch.inspect}, project_name:"\
|
|
117
|
+
" #{@project_name.inspect}, tags: #{@tags.inspect}, additional_properties:"\
|
|
118
|
+
" #{@additional_properties}>"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# semgrep_web_app
|
|
2
|
+
#
|
|
3
|
+
# This file was automatically generated by APIMATIC v3.0 (
|
|
4
|
+
# https://www.apimatic.io ).
|
|
5
|
+
|
|
6
|
+
module SemgrepWebApp
|
|
7
|
+
# Successfully updated details for the project.
|
|
8
|
+
class UpdateProjectResponse < BaseModel
|
|
9
|
+
SKIP = Object.new
|
|
10
|
+
private_constant :SKIP
|
|
11
|
+
|
|
12
|
+
# A project in your organization that uses Semgrep.
|
|
13
|
+
# @return [Project]
|
|
14
|
+
attr_accessor :project
|
|
15
|
+
|
|
16
|
+
# A mapping from model property names to API property names.
|
|
17
|
+
def self.names
|
|
18
|
+
@_hash = {} if @_hash.nil?
|
|
19
|
+
@_hash['project'] = 'project'
|
|
20
|
+
@_hash
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# An array for optional fields
|
|
24
|
+
def self.optionals
|
|
25
|
+
[]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# An array for nullable fields
|
|
29
|
+
def self.nullables
|
|
30
|
+
[]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize(project:, additional_properties: nil)
|
|
34
|
+
# Add additional model properties to the instance
|
|
35
|
+
additional_properties = {} if additional_properties.nil?
|
|
36
|
+
|
|
37
|
+
@project = project
|
|
38
|
+
@additional_properties = additional_properties
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Creates an instance of the object from a hash.
|
|
42
|
+
def self.from_hash(hash)
|
|
43
|
+
return nil unless hash
|
|
44
|
+
|
|
45
|
+
# Extract variables from the hash.
|
|
46
|
+
project = Project.from_hash(hash['project']) if hash['project']
|
|
47
|
+
|
|
48
|
+
# Create a new hash for additional properties, removing known properties.
|
|
49
|
+
new_hash = hash.reject { |k, _| names.value?(k) }
|
|
50
|
+
|
|
51
|
+
additional_properties = APIHelper.get_additional_properties(
|
|
52
|
+
new_hash, proc { |value| value }
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Create object from extracted values.
|
|
56
|
+
UpdateProjectResponse.new(project: project,
|
|
57
|
+
additional_properties: additional_properties)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Provides a human-readable string representation of the object.
|
|
61
|
+
def to_s
|
|
62
|
+
class_name = self.class.name.split('::').last
|
|
63
|
+
"<#{class_name} project: #{@project}, additional_properties: #{@additional_properties}>"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Provides a debugging-friendly string with detailed object information.
|
|
67
|
+
def inspect
|
|
68
|
+
class_name = self.class.name.split('::').last
|
|
69
|
+
"<#{class_name} project: #{@project.inspect}, additional_properties:"\
|
|
70
|
+
" #{@additional_properties}>"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|