Add Backend.devices ListModelMap

The Device ListModels will be populated after login.
This commit is contained in:
miruka 2019-05-09 13:58:46 -04:00
parent a15f6b0bac
commit 1a90bb4331
5 changed files with 79 additions and 23 deletions

View File

@ -71,3 +71,12 @@
- Distribution
- Review setup.py, add dependencies
- README.md
- Use PyInstaller or pyqtdeploy
- Test command:
```
pyinstaller --onefile --windowed --name harmonyqml \
--add-data 'harmonyqml/components:harmonyqml/components' \
--additional-hooks-dir . \
--upx-dir ~/opt/upx-3.95-amd64_linux \
run.py
```

View File

@ -30,6 +30,7 @@ class Backend(QObject):
self._accounts: ListModel = ListModel(parent=parent)
self._room_events: ListModelMap = ListModelMap(Deque, parent)
self._devices: ListModelMap = ListModelMap(parent=parent)
from .signal_manager import SignalManager
self._signal_manager: SignalManager = SignalManager(self)
@ -53,6 +54,10 @@ class Backend(QObject):
def roomEvents(self):
return self._room_events
@pyqtProperty("QVariant", constant=True)
def devices(self):
return self._devices
@pyqtProperty("QVariant", constant=True)
def signals(self):
return self._signal_manager
@ -141,6 +146,7 @@ class Backend(QObject):
cl = self.clients
ac = self.accounts
re = self.roomEvents
de = self.devices
tcl = lambda user: cl[f"@test_{user}:matrix.org"]

View File

@ -13,6 +13,7 @@ from PyQt5.QtCore import (
import nio
from .model.items import Trust
from .network_manager import NetworkManager
from .pyqt_future import PyQtFuture, futurize
@ -81,19 +82,19 @@ class Client(QObject):
@futurize(max_running=1, discard_if_max_running=True, pyqt=False)
def _keys_upload(self) -> None:
def uploadE2EKeys(self) -> None:
self.net.talk(self.nio.keys_upload)
def _keys_query(self) -> None:
def queryE2EKeys(self) -> None:
self.net.talk(self.nio.keys_query)
def _keys_claim(self, room_id: str) -> None:
def claimE2EKeysForRoom(self, room_id: str) -> None:
self.net.talk(self.nio.keys_claim, room_id)
def _share_group_session(self,
def shareRoomE2ESession(self,
room_id: str,
ignore_missing_sessions: bool = False) -> None:
self.net.talk(
@ -103,16 +104,21 @@ class Client(QObject):
)
def getDeviceTrust(self, device: nio.crypto.OlmDevice) -> Trust:
olm = self.nio.olm
return (
Trust.trusted if olm.is_device_verified(device) else
Trust.blacklisted if olm.is_device_blacklisted(device) else
Trust.undecided
)
@pyqtSlot(str, result="QVariant")
@pyqtSlot(str, str, result="QVariant")
@futurize()
def login(self, password: str, device_name: str = "") -> "Client":
response = self.net.talk(self.nio.login, password, device_name)
self.nio_sync.receive_response(response)
if not self.nio.olm_account_shared:
self._keys_upload()
return self
@ -123,10 +129,6 @@ class Client(QObject):
response = nio.LoginResponse(user_id, device_id, token)
self.nio.receive_response(response)
self.nio_sync.receive_response(response)
if not self.nio.olm_account_shared:
self._keys_upload()
return self
@ -158,10 +160,10 @@ class Client(QObject):
self.nio.receive_response(response)
if self.nio.should_upload_keys:
self._keys_upload()
self.uploadE2EKeys()
if self.nio.should_query_keys:
self._keys_query()
self.queryE2EKeys()
for room_id, room_info in response.rooms.invite.items():
for ev in room_info.invite_state:
@ -280,11 +282,11 @@ class Client(QObject):
except nio.GroupEncryptionError as err:
log.warning(err)
try:
self._share_group_session(room_id)
self.shareRoomE2ESession(room_id)
except nio.EncryptionError as err:
log.warning(err)
self._keys_claim(room_id)
self._share_group_session(room_id,
self.claimE2EKeysForRoom(room_id)
self.shareRoomE2ESession(room_id,
ignore_missing_sessions=True)
log.debug("Final try to send %r to %r", content, room_id)

View File

@ -1,3 +1,4 @@
from enum import Enum
from typing import Any, Dict, List, Optional
from PyQt5.QtCore import QDateTime, QSortFilterProxyModel
@ -42,6 +43,22 @@ class RoomCategory(ListItem):
sortedRooms: QSortFilterProxyModel = QSortFilterProxyModel()
class Trust(Enum):
blacklisted = -1
undecided = 0
trusted = 1
class Device(ListItem):
_required_init_values = {"deviceId", "ed25519Key"}
_constant = {"deviceId", "ed25519Key"}
deviceId: str = ""
ed25519Key: str = ""
displayName: Optional[str] = None
trust: Trust = Trust.undecided
class Account(ListItem):
_required_init_values = {"userId", "roomCategories"}
_constant = {"userId", "roomCategories"}

View File

@ -11,7 +11,9 @@ from nio.rooms import MatrixRoom
from .backend import Backend
from .client import Client
from .model.items import Account, ListModel, Room, RoomCategory, RoomEvent
from .model.items import (
Account, Device, ListModel, Room, RoomCategory, RoomEvent
)
from .model.sort_filter_proxy import SortFilterProxy
Inviter = Optional[Dict[str, str]]
@ -35,8 +37,7 @@ class SignalManager(QObject):
def onClientAdded(self, client: Client) -> None:
self.connectClient(client)
# Build an Account item for the Backend.accounts model
room_categories_kwargs: List[Dict[str, Any]] = [
{"name": "Invites", "rooms": ListModel()},
{"name": "Rooms", "rooms": ListModel()},
@ -59,6 +60,27 @@ class SignalManager(QObject):
displayName = self.backend.getUserDisplayName(client.userId),
))
# Upload our E2E keys to the matrix server if needed
if not client.nio.olm_account_shared:
client.uploadE2EKeys()
# Add our devices to the Backend.devices model
store = client.nio.device_store
for user_id in store.users:
self.backend.devices[user_id].clear()
self.backend.devices[user_id].extend([
Device(
deviceId = dev.id,
ed25519Key = dev.ed25519,
trust = client.getDeviceTrust(dev),
# displayName = TODO
) for dev in store.active_user_devices(user_id)
])
# Finally, connect all client signals
self.connectClient(client)
def onClientDeleted(self, user_id: str) -> None:
del self.backend.accounts[user_id]