Coverage for silkaj/wot/idty_tools.py: 100%
77 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-20 12:29 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-20 12:29 +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 arrow
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 = arrow.get(creation_block["time"]).to("local").format(ALL)
44 id_table.append(["Created on", creation_date])
45 # display infos
46 table = Texttable(max_width=shutil.get_terminal_size().columns)
47 table.add_rows(id_table, header=False)
48 return table
51def check_many_identities(document: Union[Identity, Revocation]) -> bool:
52 """
53 Checks if many identities match the one looked after.
54 Returns True if the same identity is found, False if not.
55 """
56 doc_type = document.__class__.__name__
57 error_no_identical_id = f"{doc_type} document does not match any valid identity."
58 idty = document if doc_type == "Identity" else document.identity
60 try:
61 results_pubkey = wot_lookup(idty.pubkey)
62 results_uid = wot_lookup(idty.uid)
63 except urllib.error.HTTPError:
64 sys.exit(
65 f"{error_no_identical_id}\nuid: {idty.uid}\npubkey: \
66{gen_pubkey_checksum(idty.pubkey)}",
67 )
69 # get all matching identities
70 lookup_ids = merge_ids_lists(results_pubkey, results_uid, idty.currency)
71 match = False
72 for n, lookup in enumerate(lookup_ids):
73 if idty == lookup:
74 lookup_ids.pop(n)
75 match = True
76 break
77 alternate_ids = display_alternate_ids(lookup_ids).draw()
78 if match:
79 if len(lookup_ids) >= 1:
80 click.echo(f"One matching identity!\nSimilar identities:\n{alternate_ids}")
81 return True
82 click.echo(f"{error_no_identical_id}\nSimilar identities:\n{alternate_ids}")
83 return False
86def display_alternate_ids(ids_list: list) -> Texttable:
87 labels = ["uid", "public key", "timestamp"]
88 table = Texttable(max_width=shutil.get_terminal_size().columns)
89 table.header(labels)
90 for _id in ids_list:
91 table.add_row(
92 [_id.uid, gen_pubkey_checksum(_id.pubkey), str(_id.block_id)[:12]],
93 )
94 return table
97def merge_ids_lists(lookups_pubkey: list, lookups_uid: list, currency: str) -> list:
98 """
99 merge two lists of identities and remove duplicate identities.
100 """
101 ids = ids_list_from_lookups(lookups_pubkey, currency)
102 ids_uid = ids_list_from_lookups(lookups_uid, currency)
103 for _id in ids_uid:
104 # __equal__ does not work. This is condition "id in ids".
105 for listed_id in ids:
106 if _id.signed_raw() == listed_id.signed_raw():
107 id_in_ids = True
108 break
109 id_in_ids = False
110 if not id_in_ids:
111 ids.append(_id)
112 return ids
115def ids_list_from_lookups(lookups: list, currency: str) -> list:
116 ids = []
117 for lookup in lookups:
118 pubkey = lookup["pubkey"]
119 lookup_ids = lookup["uids"]
120 for _id in lookup_ids:
121 appended_id = Identity(
122 currency=currency,
123 pubkey=pubkey,
124 uid=_id["uid"],
125 block_id=BlockID.from_str(_id["meta"]["timestamp"]),
126 )
127 appended_id.signature = _id["self"]
128 ids.append(appended_id)
129 return ids