sift_py.report_templates.service
1from __future__ import annotations 2 3from datetime import datetime 4from pathlib import Path 5from typing import Any, Dict, List, Optional, cast 6 7from google.protobuf.field_mask_pb2 import FieldMask 8from sift.report_templates.v1.report_templates_pb2 import ( 9 CreateReportTemplateRequest, 10 CreateReportTemplateRequestClientKeys, 11 GetReportTemplateRequest, 12 GetReportTemplateResponse, 13 ReportTemplate, 14 ReportTemplateRule, 15 ReportTemplateTag, 16 UpdateReportTemplateRequest, 17) 18from sift.report_templates.v1.report_templates_pb2_grpc import ReportTemplateServiceStub 19 20from sift_py._internal.time import to_timestamp_pb 21from sift_py.grpc.transport import SiftChannel 22from sift_py.report_templates.config import ReportTemplateConfig, ReportTemplateUpdate 23from sift_py.yaml.report_templates import load_report_templates 24 25 26class ReportTemplateService: 27 """ 28 A service for managing report templates. Allows for creating, updating, and retrieving report 29 templates. 30 """ 31 32 _report_template_service_stub: ReportTemplateServiceStub 33 34 def __init__(self, channel: SiftChannel): 35 self._report_template_service_stub = ReportTemplateServiceStub(channel) 36 37 def create_or_update_report_template( 38 self, config: ReportTemplateConfig, updates: Optional[ReportTemplateUpdate] = None 39 ): 40 """ 41 Create or update a report template via a ReportTemplateConfig. The config must contain a 42 template_client_key, otherwise an exception will be raised. If a report template with the 43 same client key exists, it will be updated. Otherwise, a new report template will be created. 44 See `sift_py.report_templates.config.ReportTemplateConfig` for more information on available 45 fields to configure. 46 """ 47 if updates: 48 if not config.template_client_key and not config.template_id: 49 raise Exception( 50 f"Report template {config.name} requires either a template_client_key or report_template_id to update." 51 ) 52 self._update_report_template(config, updates) 53 else: 54 self._create_report_template(config) 55 56 def get_report_template( 57 self, client_key: Optional[str] = None, id: Optional[str] = None 58 ) -> Optional[ReportTemplateConfig]: 59 """ 60 Retrieve a report template by client key or id. Only one of client_key or id should be 61 provided, otherwise an exception will be raised. If a report template is found, it will be 62 returned as a ReportTemplateConfig object. 63 """ 64 report_template = None 65 if (not client_key and not id) or (client_key and id): 66 raise ValueError("One of client_key or id must be provided") 67 68 if id: 69 report_template = self._get_report_template_by_id(id) 70 elif client_key: 71 report_template = self._get_report_template_by_client_key(client_key) 72 73 return ( 74 ReportTemplateConfig( 75 name=report_template.name, 76 template_id=report_template.report_template_id, 77 template_client_key=report_template.client_key, 78 tags=[tag.tag_name for tag in report_template.tags], 79 description=report_template.description, 80 rule_client_keys=[rule.client_key for rule in report_template.rules], 81 archived_date=report_template.archived_date.ToDatetime() 82 if report_template.archived_date 83 else None, 84 archived=True if report_template.archived_date else False, 85 ) 86 if report_template 87 else None 88 ) 89 90 def load_report_templates_from_yaml(self, paths: List[Path]) -> List[ReportTemplateConfig]: 91 """ 92 Load report templates from YAML definitions. The YAML defined report template must have 93 a client key. If the report template with the given client key exists, it will be updated, 94 otherwise a new report template will be created. 95 See `sift_py.yaml.report_templates.load_report_templates` for more information on the YAML 96 spec for report templates. 97 """ 98 report_templates = load_report_templates(paths) 99 [ 100 self.create_or_update_report_template(report_template) 101 for report_template in report_templates 102 ] 103 return report_templates 104 105 def _get_report_template_by_id(self, report_template_id: str) -> Optional[ReportTemplate]: 106 req = GetReportTemplateRequest(report_template_id=report_template_id) 107 try: 108 res = cast( 109 GetReportTemplateResponse, self._report_template_service_stub.GetReportTemplate(req) 110 ) 111 return cast(ReportTemplate, res.report_template) or None 112 except: 113 return None 114 115 def _get_report_template_by_client_key(self, client_key: str) -> Optional[ReportTemplate]: 116 req = GetReportTemplateRequest(client_key=client_key) 117 try: 118 res = cast( 119 GetReportTemplateResponse, self._report_template_service_stub.GetReportTemplate(req) 120 ) 121 return res.report_template or None 122 except: 123 return None 124 125 def _create_report_template(self, config: ReportTemplateConfig): 126 client_keys_req = CreateReportTemplateRequestClientKeys( 127 rule_client_keys=config.rule_client_keys 128 ) 129 req = CreateReportTemplateRequest( 130 name=config.name, 131 client_key=config.template_client_key, 132 description=config.description, 133 tag_names=config.tags, 134 rule_client_keys=client_keys_req, 135 ) 136 self._report_template_service_stub.CreateReportTemplate(req) 137 138 def _update_report_template(self, config: ReportTemplateConfig, updates: ReportTemplateUpdate): 139 """ 140 Updates a report template using the provided updates. Only the fields specified in the updates 141 will be modified. 142 """ 143 update_map: Dict[str, Any] = {} 144 if "name" in updates: 145 update_map["name"] = updates["name"] 146 if "description" in updates: 147 update_map["description"] = updates["description"] 148 if "tags" in updates: 149 update_map["tags"] = [ReportTemplateTag(tag_name=tag) for tag in updates["tags"]] 150 if "rule_client_keys" in updates: 151 update_map["rules"] = [ 152 ReportTemplateRule(client_key=client_key) 153 for client_key in updates["rule_client_keys"] 154 ] 155 if "archived" in updates: 156 update_map["archived_date"] = ( 157 to_timestamp_pb(datetime.now()) if updates["archived"] else None 158 ) 159 160 updated_report_template = ReportTemplate( 161 report_template_id=config.template_id or "", 162 client_key=config.template_client_key, 163 name=update_map.get("name", config.name), 164 description=update_map.get("description", config.description), 165 tags=update_map.get("tags", config.tags), 166 rules=update_map.get( 167 "rules", [ReportTemplateRule(client_key=key) for key in config.rule_client_keys] 168 ), 169 archived_date=update_map.get("archived_date", config.archived_date), 170 ) 171 172 field_mask = FieldMask(paths=list(update_map.keys())) 173 self._report_template_service_stub.UpdateReportTemplate( 174 UpdateReportTemplateRequest( 175 report_template=updated_report_template, update_mask=field_mask 176 ) 177 )
27class ReportTemplateService: 28 """ 29 A service for managing report templates. Allows for creating, updating, and retrieving report 30 templates. 31 """ 32 33 _report_template_service_stub: ReportTemplateServiceStub 34 35 def __init__(self, channel: SiftChannel): 36 self._report_template_service_stub = ReportTemplateServiceStub(channel) 37 38 def create_or_update_report_template( 39 self, config: ReportTemplateConfig, updates: Optional[ReportTemplateUpdate] = None 40 ): 41 """ 42 Create or update a report template via a ReportTemplateConfig. The config must contain a 43 template_client_key, otherwise an exception will be raised. If a report template with the 44 same client key exists, it will be updated. Otherwise, a new report template will be created. 45 See `sift_py.report_templates.config.ReportTemplateConfig` for more information on available 46 fields to configure. 47 """ 48 if updates: 49 if not config.template_client_key and not config.template_id: 50 raise Exception( 51 f"Report template {config.name} requires either a template_client_key or report_template_id to update." 52 ) 53 self._update_report_template(config, updates) 54 else: 55 self._create_report_template(config) 56 57 def get_report_template( 58 self, client_key: Optional[str] = None, id: Optional[str] = None 59 ) -> Optional[ReportTemplateConfig]: 60 """ 61 Retrieve a report template by client key or id. Only one of client_key or id should be 62 provided, otherwise an exception will be raised. If a report template is found, it will be 63 returned as a ReportTemplateConfig object. 64 """ 65 report_template = None 66 if (not client_key and not id) or (client_key and id): 67 raise ValueError("One of client_key or id must be provided") 68 69 if id: 70 report_template = self._get_report_template_by_id(id) 71 elif client_key: 72 report_template = self._get_report_template_by_client_key(client_key) 73 74 return ( 75 ReportTemplateConfig( 76 name=report_template.name, 77 template_id=report_template.report_template_id, 78 template_client_key=report_template.client_key, 79 tags=[tag.tag_name for tag in report_template.tags], 80 description=report_template.description, 81 rule_client_keys=[rule.client_key for rule in report_template.rules], 82 archived_date=report_template.archived_date.ToDatetime() 83 if report_template.archived_date 84 else None, 85 archived=True if report_template.archived_date else False, 86 ) 87 if report_template 88 else None 89 ) 90 91 def load_report_templates_from_yaml(self, paths: List[Path]) -> List[ReportTemplateConfig]: 92 """ 93 Load report templates from YAML definitions. The YAML defined report template must have 94 a client key. If the report template with the given client key exists, it will be updated, 95 otherwise a new report template will be created. 96 See `sift_py.yaml.report_templates.load_report_templates` for more information on the YAML 97 spec for report templates. 98 """ 99 report_templates = load_report_templates(paths) 100 [ 101 self.create_or_update_report_template(report_template) 102 for report_template in report_templates 103 ] 104 return report_templates 105 106 def _get_report_template_by_id(self, report_template_id: str) -> Optional[ReportTemplate]: 107 req = GetReportTemplateRequest(report_template_id=report_template_id) 108 try: 109 res = cast( 110 GetReportTemplateResponse, self._report_template_service_stub.GetReportTemplate(req) 111 ) 112 return cast(ReportTemplate, res.report_template) or None 113 except: 114 return None 115 116 def _get_report_template_by_client_key(self, client_key: str) -> Optional[ReportTemplate]: 117 req = GetReportTemplateRequest(client_key=client_key) 118 try: 119 res = cast( 120 GetReportTemplateResponse, self._report_template_service_stub.GetReportTemplate(req) 121 ) 122 return res.report_template or None 123 except: 124 return None 125 126 def _create_report_template(self, config: ReportTemplateConfig): 127 client_keys_req = CreateReportTemplateRequestClientKeys( 128 rule_client_keys=config.rule_client_keys 129 ) 130 req = CreateReportTemplateRequest( 131 name=config.name, 132 client_key=config.template_client_key, 133 description=config.description, 134 tag_names=config.tags, 135 rule_client_keys=client_keys_req, 136 ) 137 self._report_template_service_stub.CreateReportTemplate(req) 138 139 def _update_report_template(self, config: ReportTemplateConfig, updates: ReportTemplateUpdate): 140 """ 141 Updates a report template using the provided updates. Only the fields specified in the updates 142 will be modified. 143 """ 144 update_map: Dict[str, Any] = {} 145 if "name" in updates: 146 update_map["name"] = updates["name"] 147 if "description" in updates: 148 update_map["description"] = updates["description"] 149 if "tags" in updates: 150 update_map["tags"] = [ReportTemplateTag(tag_name=tag) for tag in updates["tags"]] 151 if "rule_client_keys" in updates: 152 update_map["rules"] = [ 153 ReportTemplateRule(client_key=client_key) 154 for client_key in updates["rule_client_keys"] 155 ] 156 if "archived" in updates: 157 update_map["archived_date"] = ( 158 to_timestamp_pb(datetime.now()) if updates["archived"] else None 159 ) 160 161 updated_report_template = ReportTemplate( 162 report_template_id=config.template_id or "", 163 client_key=config.template_client_key, 164 name=update_map.get("name", config.name), 165 description=update_map.get("description", config.description), 166 tags=update_map.get("tags", config.tags), 167 rules=update_map.get( 168 "rules", [ReportTemplateRule(client_key=key) for key in config.rule_client_keys] 169 ), 170 archived_date=update_map.get("archived_date", config.archived_date), 171 ) 172 173 field_mask = FieldMask(paths=list(update_map.keys())) 174 self._report_template_service_stub.UpdateReportTemplate( 175 UpdateReportTemplateRequest( 176 report_template=updated_report_template, update_mask=field_mask 177 ) 178 )
A service for managing report templates. Allows for creating, updating, and retrieving report templates.
38 def create_or_update_report_template( 39 self, config: ReportTemplateConfig, updates: Optional[ReportTemplateUpdate] = None 40 ): 41 """ 42 Create or update a report template via a ReportTemplateConfig. The config must contain a 43 template_client_key, otherwise an exception will be raised. If a report template with the 44 same client key exists, it will be updated. Otherwise, a new report template will be created. 45 See `sift_py.report_templates.config.ReportTemplateConfig` for more information on available 46 fields to configure. 47 """ 48 if updates: 49 if not config.template_client_key and not config.template_id: 50 raise Exception( 51 f"Report template {config.name} requires either a template_client_key or report_template_id to update." 52 ) 53 self._update_report_template(config, updates) 54 else: 55 self._create_report_template(config)
Create or update a report template via a ReportTemplateConfig. The config must contain a
template_client_key, otherwise an exception will be raised. If a report template with the
same client key exists, it will be updated. Otherwise, a new report template will be created.
See sift_py.report_templates.config.ReportTemplateConfig
for more information on available
fields to configure.
57 def get_report_template( 58 self, client_key: Optional[str] = None, id: Optional[str] = None 59 ) -> Optional[ReportTemplateConfig]: 60 """ 61 Retrieve a report template by client key or id. Only one of client_key or id should be 62 provided, otherwise an exception will be raised. If a report template is found, it will be 63 returned as a ReportTemplateConfig object. 64 """ 65 report_template = None 66 if (not client_key and not id) or (client_key and id): 67 raise ValueError("One of client_key or id must be provided") 68 69 if id: 70 report_template = self._get_report_template_by_id(id) 71 elif client_key: 72 report_template = self._get_report_template_by_client_key(client_key) 73 74 return ( 75 ReportTemplateConfig( 76 name=report_template.name, 77 template_id=report_template.report_template_id, 78 template_client_key=report_template.client_key, 79 tags=[tag.tag_name for tag in report_template.tags], 80 description=report_template.description, 81 rule_client_keys=[rule.client_key for rule in report_template.rules], 82 archived_date=report_template.archived_date.ToDatetime() 83 if report_template.archived_date 84 else None, 85 archived=True if report_template.archived_date else False, 86 ) 87 if report_template 88 else None 89 )
Retrieve a report template by client key or id. Only one of client_key or id should be provided, otherwise an exception will be raised. If a report template is found, it will be returned as a ReportTemplateConfig object.
91 def load_report_templates_from_yaml(self, paths: List[Path]) -> List[ReportTemplateConfig]: 92 """ 93 Load report templates from YAML definitions. The YAML defined report template must have 94 a client key. If the report template with the given client key exists, it will be updated, 95 otherwise a new report template will be created. 96 See `sift_py.yaml.report_templates.load_report_templates` for more information on the YAML 97 spec for report templates. 98 """ 99 report_templates = load_report_templates(paths) 100 [ 101 self.create_or_update_report_template(report_template) 102 for report_template in report_templates 103 ] 104 return report_templates
Load report templates from YAML definitions. The YAML defined report template must have
a client key. If the report template with the given client key exists, it will be updated,
otherwise a new report template will be created.
See sift_py.yaml.report_templates.load_report_templates
for more information on the YAML
spec for report templates.