Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions weblate/vcs/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import subprocess
from base64 import b64decode, b64encode
from contextlib import suppress
from typing import TYPE_CHECKING, Literal, TypedDict
from typing import TYPE_CHECKING, Any, Literal, NotRequired, TypedDict
from urllib.parse import urlparse

from django.conf import settings
Expand All @@ -26,6 +26,7 @@
from weblate.utils.validators import DomainOrIPValidator

if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path

from django_stubs_ext import StrOrPromise
Expand All @@ -46,6 +47,16 @@ class KeyInfo(TypedDict):

KeyType = Literal["rsa", "ed25519"]


class KeyDetails(TypedDict):
key: str | None
fingerprint: NotRequired[str]
id: NotRequired[str]
filename: NotRequired[str]
type: KeyType
name: StrOrPromise


KEYS: dict[KeyType, KeyInfo] = {
"rsa": {
"private": "id_rsa",
Expand Down Expand Up @@ -121,7 +132,7 @@ def get_key_data_raw(
return filename, None


def get_key_data(key_type: KeyType = "rsa") -> dict[str, StrOrPromise | None]:
def get_key_data(key_type: KeyType = "rsa") -> KeyDetails:
"""Parse host key and returns it."""
filename, key_data = get_key_data_raw(key_type)
if key_data is not None:
Expand All @@ -141,12 +152,12 @@ def get_key_data(key_type: KeyType = "rsa") -> dict[str, StrOrPromise | None]:
}


def get_all_key_data() -> dict[str, dict[str, StrOrPromise | None]]:
def get_all_key_data() -> dict[KeyType, KeyDetails]:
"""Return all supported SSH keys."""
return {key_type: get_key_data(key_type) for key_type in KEYS}


def ensure_ssh_key():
def ensure_ssh_key() -> KeyDetails | None:
"""Ensure SSH key is existing."""
result = None
for key_type in KEYS:
Expand Down Expand Up @@ -300,11 +311,14 @@ def add_host_key(
)


def cleanup_host_keys(*args, **kwargs) -> None:
def cleanup_host_keys(
*args: Any, # noqa: ANN401
logger: Callable[[str], Any] = print,
**kwargs: Any, # noqa: ANN401
) -> None:
known_hosts_file = ssh_file(KNOWN_HOSTS)
if not known_hosts_file.exists():
return
logger = kwargs.get("logger", print)
keys = []
with known_hosts_file.open() as handle:
for line in handle:
Expand All @@ -327,7 +341,7 @@ def cleanup_host_keys(*args, **kwargs) -> None:
handle.writelines(keys)


def can_generate_key():
def can_generate_key() -> bool:
"""Check whether we can generate key."""
return find_command("ssh-keygen") is not None

Expand Down
Loading