Coverage for silkaj/wot/idty_tools.py: 100%
77 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-22 12:04 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-22 12:04 +0000
1# Copyright 2016-2025 Maël Azimi <m.a@moul.re>
2#
3# Silkaj is free software: you can redistribute it and/or modify
4# it under the terms of the GNU Affero General Public License as published by
5# the Free Software Foundation, either version 3 of the License, or
6# (at your option) any later version.
7#
8# Silkaj is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU Affero General Public License for more details.
12#
13# You should have received a copy of the GNU Affero General Public License
14# along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
16import shutil
17import sys
18import urllib
19from typing import Union
21import pendulum
22import rich_click as click
23from duniterpy.api import bma
24from duniterpy.documents import BlockID, Identity, Revocation
25from texttable import Texttable
27from silkaj.constants import ALL
28from silkaj.network import client_instance
29from silkaj.public_key import gen_pubkey_checksum
30from silkaj.wot.tools import wot_lookup
33def display_identity(idty: Identity) -> Texttable:
34 """
35 Creates a table containing the identity infos
36 """
37 client = client_instance()
38 id_table = []
39 id_table.append(["Public key", gen_pubkey_checksum(idty.pubkey)])
40 id_table.append(["User ID", idty.uid])
41 id_table.append(["Blockstamp", str(idty.block_id)])
42 creation_block = client(bma.blockchain.block, idty.block_id.number)
43 creation_date = pendulum.from_timestamp(creation_block["time"], tz="local").format(
44 ALL,
45 )
46 id_table.append(["Created on", creation_date])
47 # display infos
48 table = Texttable(max_width=shutil.get_terminal_size().columns)
49 table.add_rows(id_table, header=False)
50 return table
53def check_many_identities(document: Union[Identity, Revocation]) -> bool:
54 """
55 Checks if many identities match the one looked after.
56 Returns True if the same identity is found, False if not.
57 """
58 doc_type = document.__class__.__name__
59 error_no_identical_id = f"{doc_type} document does not match any valid identity."
60 idty = document if doc_type == "Identity" else document.identity
62 try:
63 results_pubkey = wot_lookup(idty.pubkey)
64 results_uid = wot_lookup(idty.uid)
65 except urllib.error.HTTPError:
66 sys.exit(
67 f"{error_no_identical_id}\nuid: {idty.uid}\npubkey: \
68{gen_pubkey_checksum(idty.pubkey)}",
69 )
71 # get all matching identities
72 lookup_ids = merge_ids_lists(results_pubkey, results_uid, idty.currency)
73 match = False
74 for n, lookup in enumerate(lookup_ids):
75 if idty == lookup:
76 lookup_ids.pop(n)
77 match = True
78 break
79 alternate_ids = display_alternate_ids(lookup_ids).draw()
80 if match:
81 if len(lookup_ids) >= 1:
82 click.echo(f"One matching identity!\nSimilar identities:\n{alternate_ids}")
83 return True
84 click.echo(f"{error_no_identical_id}\nSimilar identities:\n{alternate_ids}")
85 return False
88def display_alternate_ids(ids_list: list) -> Texttable:
89 labels = ["uid", "public key", "timestamp"]
90 table = Texttable(max_width=shutil.get_terminal_size().columns)
91 table.header(labels)
92 for _id in ids_list:
93 table.add_row(
94 [_id.uid, gen_pubkey_checksum(_id.pubkey), str(_id.block_id)[:12]],
95 )
96 return table
99def merge_ids_lists(lookups_pubkey: list, lookups_uid: list, currency: str) -> list:
100 """
101 merge two lists of identities and remove duplicate identities.
102 """
103 ids = ids_list_from_lookups(lookups_pubkey, currency)
104 ids_uid = ids_list_from_lookups(lookups_uid, currency)
105 for _id in ids_uid:
106 # __equal__ does not work. This is condition "id in ids".
107 for listed_id in ids:
108 if _id.signed_raw() == listed_id.signed_raw():
109 id_in_ids = True
110 break
111 id_in_ids = False
112 if not id_in_ids:
113 ids.append(_id)
114 return ids
117def ids_list_from_lookups(lookups: list, currency: str) -> list:
118 ids = []
119 for lookup in lookups:
120 pubkey = lookup["pubkey"]
121 lookup_ids = lookup["uids"]
122 for _id in lookup_ids:
123 appended_id = Identity(
124 currency=currency,
125 pubkey=pubkey,
126 uid=_id["uid"],
127 block_id=BlockID.from_str(_id["meta"]["timestamp"]),
128 )
129 appended_id.signature = _id["self"]
130 ids.append(appended_id)
131 return ids