Exemple #1
0
    def add_detached_bank_member_signal(bank_id=None) -> BankMemberSignal:
        """
        Add a virtual bank_member (without any associated media) and a
        corresponding signal.

        Requires JSON object with following fields:
        - signal_type: ["pdq"|"pdq_ocr","photo_md5"] -> anything from
          threatexchange.content_type.meta.get_signal_types_by_name()'s keys
        - content_type: ["photo"|"video"] to get the content_type for the
          virtual member.
        - signal_value: the hash to store against this signal. Will
          automatically de-dupe against existing signals.
        """
        content_type = get_content_type_for_name(
            bottle.request.json["content_type"])
        signal_type = get_signal_types_by_name()[
            bottle.request.json["signal_type"]]
        signal_value = bottle.request.json["signal_value"]

        return bank_ops.add_detached_bank_member_signal(
            banks_table=table_manager,
            bank_id=bank_id,
            content_type=content_type,
            signal_type=signal_type,
            signal_value=signal_value,
        )
Exemple #2
0
 def from_sqs_message(cls, d: dict) -> "PipelineHashRecord":
     return cls(
         content_id=d["ContentId"],
         signal_type=get_signal_types_by_name()[d["SignalType"]],
         content_hash=d["ContentHash"],
         signal_specific_attributes=d["SignalSpecificAttributes"],
         updated_at=datetime.datetime.fromisoformat(d["UpdatedAt"]),
     )
Exemple #3
0
 def from_dynamodb_item(cls, item: t.Dict) -> "BankMemberSignal":
     return cls(
         bank_id=item["BankId"],
         bank_member_id=item["BankMemberId"],
         signal_id=item["SignalId"],
         signal_type=get_signal_types_by_name()[item["SignalType"]],
         signal_value=item["SignalValue"],
         updated_at=datetime.fromisoformat(item["UpdatedAt"]),
     )
Exemple #4
0
 def _result_item_to_metadata(
     cls,
     item: t.Dict,
 ) -> "ThreatExchangeSignalMetadata":
     return ThreatExchangeSignalMetadata(
         signal_id=cls.remove_signal_key_prefix(item["PK"], item["SignalSource"]),
         privacy_group_id=item["PrivacyGroup"],
         updated_at=datetime.datetime.fromisoformat(item["UpdatedAt"]),
         signal_type=get_signal_types_by_name()[item["SignalType"]],
         signal_hash=item["SignalHash"],
         tags=item["Tags"],
         pending_opinion_change=PendingThreatExchangeOpinionChange(
             item.get(
                 "PendingThreatExchangeOpinionChange",
                 PendingThreatExchangeOpinionChange.NONE.value,
             )
         ),
     )
Exemple #5
0
 def _result_items_to_records(
     cls,
     items: t.List[t.Dict],
 ) -> t.List["MatchRecord"]:
     return [
         MatchRecord(
             content_id=cls.remove_content_key_prefix(item["PK"]),
             content_hash=item["ContentHash"],
             updated_at=datetime.datetime.fromisoformat(item["UpdatedAt"]),
             signal_type=get_signal_types_by_name()[item["SignalType"]],
             signal_id=cls.remove_signal_key_prefix(item["SK"],
                                                    item["SignalSource"]),
             signal_source=item["SignalSource"],
             signal_hash=item["SignalHash"],
             signal_specific_attributes=cls.
             deserialize_signal_specific_attributes(item),
         ) for item in items
     ]
Exemple #6
0
 def _result_items_to_records(
     cls,
     items: t.List[t.Dict],
 ) -> t.List["PipelineHashRecord"]:
     """
     Get a paginated list of recent hash records. Subsequent calls must use
     `return_value.last_evaluated_key`.
     """
     return [
         PipelineHashRecord(
             content_id=item["PK"][len(cls.CONTENT_KEY_PREFIX):],
             signal_type=get_signal_types_by_name()[item["SignalType"]],
             content_hash=item["ContentHash"],
             updated_at=datetime.datetime.fromisoformat(item["UpdatedAt"]),
             signal_specific_attributes=cls.
             deserialize_signal_specific_attributes(item),
         ) for item in items
     ]
Exemple #7
0
    def get_unique(cls, table: Table, signal_type: t.Type[SignalType],
                   signal_value: str) -> "BankedSignalEntry":
        """
        Write to the table if PK / SK does not exist. In either case (exists,
        not exists), return the current unique entry.

        This is a special use-case for BankedSignalEntry. If this is useful to
        other models, we can move it to a mixin or to dynamodb item. If trying
        to generify, note how the update_item query needs a custom update query
        based on what you are trying to write. Generifying may be harder than it
        seems.
        """
        result = table.update_item(
            Key={
                "PK": cls.get_pk(signal_type),
                "SK": cls.get_sk(signal_value),
            },
            UpdateExpression=
            "SET SignalId = if_not_exists(SignalId, :signal_id), SignalType = :signal_type, SignalValue = :signal_value",
            ExpressionAttributeValues={
                # Note we are generating a new uuid even though we don't always
                # expect it to get written. AFAIK, uuids are inexhaustible, and
                # generation performance is good enough to not worry about it.
                ":signal_id": str(uuid.uuid4()),
                ":signal_type": signal_type.get_name(),
                ":signal_value": signal_value,
            },
            ReturnValues="ALL_NEW",
        ).get("Attributes")

        assert result is not None

        return BankedSignalEntry(
            signal_type=get_signal_types_by_name()[result["SignalType"]],
            signal_value=t.cast(str, result["SignalValue"]),
            signal_id=t.cast(str, result["SignalId"]),
        )
Exemple #8
0
 def from_dict(cls, d):
     base = super().from_dict(d)
     base.signal_type = get_signal_types_by_name()[base.signal_type]
     return base
Exemple #9
0
 def from_dict(cls, d):
     base = cls(
         **{f.name: d.get(f.name, None)
            for f in dataclasses.fields(cls)})
     base.signal_type = get_signal_types_by_name()[base.signal_type]
     return base