@@ -168,8 +168,8 @@ def _validate_query_string(self, query: str, param_name: str = "query") -> None:
168168
169169 # Basic J1QL validation
170170 query_upper = query .upper ().strip ()
171- if not query_upper .startswith (( 'FIND' , 'MATCH' , 'RETURN' ) ):
172- raise JupiterOneClientError (f"{ param_name } must be a valid J1QL query starting with FIND, MATCH, or RETURN " )
171+ if not query_upper .startswith ('FIND' ):
172+ raise JupiterOneClientError (f"{ param_name } must be a valid J1QL query starting with FIND (case-insensitive) " )
173173
174174 def _validate_properties (self , properties : Dict [str , Any ], param_name : str = "properties" ) -> None :
175175 """Validate entity/relationship properties"""
@@ -216,6 +216,11 @@ def token(self, value: Optional[str]) -> None:
216216 # pylint: disable=R1710
217217 def _execute_query (self , query : str , variables : Optional [Dict [str , Any ]] = None ) -> Dict [str , Any ]:
218218 """Executes query against graphql endpoint"""
219+ # Validate credentials before making API calls
220+ if not self .account :
221+ raise JupiterOneClientError ("Account is required. Please set the account property." )
222+ if not self .token :
223+ raise JupiterOneClientError ("Token is required. Please set the token property." )
219224
220225 data : Dict [str , Any ] = {"query" : query }
221226 if variables :
@@ -483,6 +488,11 @@ def query_with_deferred_response(self, query: str, cursor: Optional[str] = None)
483488
484489 def _execute_syncapi_request (self , endpoint : str , payload : Optional [Dict [str , Any ]] = None ) -> Dict [str , Any ]:
485490 """Executes POST request to SyncAPI endpoints"""
491+ # Validate credentials before making API calls
492+ if not self .account :
493+ raise JupiterOneClientError ("Account is required. Please set the account property." )
494+ if not self .token :
495+ raise JupiterOneClientError ("Token is required. Please set the token property." )
486496
487497 # initiate requests session and implement retry logic of 5 request retries with 1 second between retries
488498 response = self .session .post (
@@ -589,6 +599,34 @@ def create_entity(self, **kwargs: Any) -> Dict[str, Any]:
589599 timestamp (int): Specify createdOn timestamp
590600 properties (dict): Dictionary of key/value entity properties
591601 """
602+ # Validate required parameters
603+ entity_key = kwargs .get ("entity_key" )
604+ entity_type = kwargs .get ("entity_type" )
605+ entity_class = kwargs .get ("entity_class" )
606+
607+ if not entity_key :
608+ raise JupiterOneClientError ("entity_key is required" )
609+ if not isinstance (entity_key , str ) or not entity_key .strip ():
610+ raise JupiterOneClientError ("entity_key must be a non-empty string" )
611+
612+ if not entity_type :
613+ raise JupiterOneClientError ("entity_type is required" )
614+ if not isinstance (entity_type , str ) or not entity_type .strip ():
615+ raise JupiterOneClientError ("entity_type must be a non-empty string" )
616+
617+ if not entity_class :
618+ raise JupiterOneClientError ("entity_class is required" )
619+ if not isinstance (entity_class , str ) or not entity_class .strip ():
620+ raise JupiterOneClientError ("entity_class must be a non-empty string" )
621+
622+ # Validate properties if provided
623+ if "properties" in kwargs and kwargs ["properties" ] is not None :
624+ self ._validate_properties (kwargs ["properties" ])
625+
626+ # Validate timestamp if provided
627+ if "timestamp" in kwargs and kwargs ["timestamp" ] is not None :
628+ if not isinstance (kwargs ["timestamp" ], int ) or kwargs ["timestamp" ] <= 0 :
629+ raise JupiterOneClientError ("timestamp must be a positive integer" )
592630 variables = {
593631 "entityKey" : kwargs .pop ("entity_key" ),
594632 "entityType" : kwargs .pop ("entity_type" ),
@@ -614,6 +652,19 @@ def delete_entity(self, entity_id: Optional[str] = None, timestamp: Optional[int
614652 timestamp (int, optional): Timestamp for the deletion. Defaults to None.
615653 hard_delete (bool): Whether to perform a hard delete. Defaults to True.
616654 """
655+ # Validate required parameters
656+ if not entity_id :
657+ raise JupiterOneClientError ("entity_id is required" )
658+ self ._validate_entity_id (entity_id )
659+
660+ # Validate timestamp if provided
661+ if timestamp is not None :
662+ if not isinstance (timestamp , int ) or timestamp <= 0 :
663+ raise JupiterOneClientError ("timestamp must be a positive integer" )
664+
665+ # Validate hard_delete
666+ if not isinstance (hard_delete , bool ):
667+ raise JupiterOneClientError ("hard_delete must be a boolean" )
617668 variables : Dict [str , Any ] = {"entityId" : entity_id , "hardDelete" : hard_delete }
618669 if timestamp :
619670 variables ["timestamp" ] = timestamp
@@ -628,6 +679,14 @@ def update_entity(self, entity_id: Optional[str] = None, properties: Optional[Di
628679 entity_id (str): The _id of the entity to update
629680 properties (dict): Dictionary of key/value entity properties
630681 """
682+ # Validate required parameters
683+ if not entity_id :
684+ raise JupiterOneClientError ("entity_id is required" )
685+ self ._validate_entity_id (entity_id )
686+
687+ if not properties :
688+ raise JupiterOneClientError ("properties is required" )
689+ self ._validate_properties (properties )
631690 variables = {"entityId" : entity_id , "properties" : properties }
632691 response = self ._execute_query (UPDATE_ENTITY , variables = variables )
633692 return response ["data" ]["updateEntity" ]
@@ -643,6 +702,39 @@ def create_relationship(self, **kwargs: Any) -> Dict[str, Any]:
643702 from_entity_id (str): Entity ID of the source vertex
644703 to_entity_id (str): Entity ID of the destination vertex
645704 """
705+ # Validate required parameters
706+ relationship_key = kwargs .get ("relationship_key" )
707+ relationship_type = kwargs .get ("relationship_type" )
708+ relationship_class = kwargs .get ("relationship_class" )
709+ from_entity_id = kwargs .get ("from_entity_id" )
710+ to_entity_id = kwargs .get ("to_entity_id" )
711+
712+ if not relationship_key :
713+ raise JupiterOneClientError ("relationship_key is required" )
714+ if not isinstance (relationship_key , str ) or not relationship_key .strip ():
715+ raise JupiterOneClientError ("relationship_key must be a non-empty string" )
716+
717+ if not relationship_type :
718+ raise JupiterOneClientError ("relationship_type is required" )
719+ if not isinstance (relationship_type , str ) or not relationship_type .strip ():
720+ raise JupiterOneClientError ("relationship_type must be a non-empty string" )
721+
722+ if not relationship_class :
723+ raise JupiterOneClientError ("relationship_class is required" )
724+ if not isinstance (relationship_class , str ) or not relationship_class .strip ():
725+ raise JupiterOneClientError ("relationship_class must be a non-empty string" )
726+
727+ if not from_entity_id :
728+ raise JupiterOneClientError ("from_entity_id is required" )
729+ self ._validate_entity_id (from_entity_id , "from_entity_id" )
730+
731+ if not to_entity_id :
732+ raise JupiterOneClientError ("to_entity_id is required" )
733+ self ._validate_entity_id (to_entity_id , "to_entity_id" )
734+
735+ # Validate properties if provided
736+ if "properties" in kwargs and kwargs ["properties" ] is not None :
737+ self ._validate_properties (kwargs ["properties" ])
646738 variables = {
647739 "relationshipKey" : kwargs .pop ("relationship_key" ),
648740 "relationshipType" : kwargs .pop ("relationship_type" ),
0 commit comments