capyy 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: capyy
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Tiny encrypted JSON-over-TCP APIs: call a function in another program, on your Wi-Fi or across the internet
5
5
  Author: Izac
6
6
  License-Expression: MIT
@@ -81,6 +81,8 @@ Everything is encrypted by default, with nothing to configure.
81
81
  and prints its **fingerprint**.
82
82
  - Like SSH, a client **remembers a server's fingerprint** the first time (`~/.capy/known_hosts.json`)
83
83
  and raises `capy.SecurityError` if it ever changes.
84
+ - The server logs every request, but **never secrets**: parameters whose name contains
85
+ `password`, `pwd`, `mdp`, `secret` or `token` are shown as `"***"`.
84
86
  - Use `tls=False` on **both** sides to talk in clear (faster on localhost).
85
87
 
86
88
  ## `capy.wifi` — find each other on the same network
@@ -59,6 +59,8 @@ Everything is encrypted by default, with nothing to configure.
59
59
  and prints its **fingerprint**.
60
60
  - Like SSH, a client **remembers a server's fingerprint** the first time (`~/.capy/known_hosts.json`)
61
61
  and raises `capy.SecurityError` if it ever changes.
62
+ - The server logs every request, but **never secrets**: parameters whose name contains
63
+ `password`, `pwd`, `mdp`, `secret` or `token` are shown as `"***"`.
62
64
  - Use `tls=False` on **both** sides to talk in clear (faster on localhost).
63
65
 
64
66
  ## `capy.wifi` — find each other on the same network
@@ -53,7 +53,7 @@ class Server:
53
53
  conn.sendall((jsonlib.dumps(self.handle(line), ensure_ascii=False) + "\n").encode())
54
54
  except (OSError, ValueError):
55
55
  return
56
- print(f"{addr[0]} → {line.strip()}")
56
+ print(f"{addr[0]} → {_hide(line)}")
57
57
 
58
58
  # port 0 -> le système choisit un port libre
59
59
  def run(self, port=None):
@@ -75,6 +75,25 @@ class Server:
75
75
 
76
76
 
77
77
  # Renvoyer du JSON écrit en texte depuis une action
78
+ # Paramètres jamais affichés dans le journal du serveur (mots de passe, tokens…)
79
+ SECRETS = ("password", "passwd", "pwd", "mdp", "motdepasse", "secret", "token")
80
+
81
+
82
+ # Une requête -> texte pour le journal, avec les secrets remplacés par "***"
83
+ # Ex : {"action": "login", "password": "1234"} -> {"action": "login", "password": "***"}
84
+ def _hide(line):
85
+ try:
86
+ request = jsonlib.loads(line) if isinstance(line, str) else dict(line)
87
+ except (ValueError, TypeError):
88
+ return str(line).strip()
89
+ if not isinstance(request, dict):
90
+ return str(line).strip()
91
+ for key in request:
92
+ if any(word in key.lower() for word in SECRETS):
93
+ request[key] = "***"
94
+ return jsonlib.dumps(request, ensure_ascii=False)
95
+
96
+
78
97
  # Ex : return capy.json('{"text": "Hello"}')
79
98
  def json(text):
80
99
  try:
@@ -366,7 +366,7 @@ class Server(capy.Server):
366
366
  channel.send({"id": message.get("id"), "response": response})
367
367
  except ConnectionError:
368
368
  return
369
- _log(f"réseau → {jsonlib.dumps(message['request'], ensure_ascii=False)}")
369
+ _log(f"réseau → {capy._hide(message['request'])}")
370
370
 
371
371
 
372
372
  # ============================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: capyy
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Tiny encrypted JSON-over-TCP APIs: call a function in another program, on your Wi-Fi or across the internet
5
5
  Author: Izac
6
6
  License-Expression: MIT
@@ -81,6 +81,8 @@ Everything is encrypted by default, with nothing to configure.
81
81
  and prints its **fingerprint**.
82
82
  - Like SSH, a client **remembers a server's fingerprint** the first time (`~/.capy/known_hosts.json`)
83
83
  and raises `capy.SecurityError` if it ever changes.
84
+ - The server logs every request, but **never secrets**: parameters whose name contains
85
+ `password`, `pwd`, `mdp`, `secret` or `token` are shown as `"***"`.
84
86
  - Use `tls=False` on **both** sides to talk in clear (faster on localhost).
85
87
 
86
88
  ## `capy.wifi` — find each other on the same network
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "capyy"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Tiny encrypted JSON-over-TCP APIs: call a function in another program, on your Wi-Fi or across the internet"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -68,6 +68,12 @@ class TestHandle(unittest.TestCase):
68
68
  self.assertEqual(self.api.handle('{"action": "divide", "a": 1, "b": 0}'), {"erreur": "division by zero"})
69
69
  self.assertIn("erreur", self.api.handle('{"action": "divide"}'))
70
70
 
71
+ def test_hide_secrets(self):
72
+ line = '{"action": "login", "name": "Zoe", "password": "1234", "user_token": "abc"}'
73
+ self.assertEqual(capy._hide(line), '{"action": "login", "name": "Zoe", "password": "***", "user_token": "***"}')
74
+ self.assertEqual(capy._hide({"mdp": "x"}), '{"mdp": "***"}')
75
+ self.assertEqual(capy._hide("pas du json\n"), "pas du json")
76
+
71
77
 
72
78
  class TestValues(unittest.TestCase):
73
79
  data = {"city": "Paris", "temp": "18.5", "rain": "non", "days": [{"name": "lundi"}, {"name": "mardi"}]}
File without changes
File without changes
File without changes
File without changes
File without changes