Properly handle login errors with new exceptions

This commit is contained in:
miruka 2019-11-11 06:39:11 -04:00
parent de7053f196
commit 7f48c1b35d
4 changed files with 48 additions and 15 deletions

View File

@ -4,8 +4,6 @@
- Handle upload errors: non existent path, path is a dir, file too big, etc - Handle upload errors: non existent path, path is a dir, file too big, etc
- Show real progression for mxc thumbnail loadings, uploads and downloads - Show real progression for mxc thumbnail loadings, uploads and downloads
- Login & upload: use new exception python/qml mechanism
- Support m.file thumbnails - Support m.file thumbnails
- Generate video thumbnails - Generate video thumbnails
- GIFs can use the video player - GIFs can use the video player
@ -201,6 +199,12 @@
- Support "Empty room (was ...)" after peer left - Support "Empty room (was ...)" after peer left
- Previewing room without joining - Previewing room without joining
- thumbnail API shouldn't require auth
- get content repo config API
- add the `resume()` method
- See if we can turn all the Error classes into actual exceptions
- Distribution - Distribution
- Include python dependencies in binary with rcc? - Include python dependencies in binary with rcc?
- README.md - README.md

View File

@ -8,7 +8,7 @@ import hsluv
import nio import nio
from .app import App from .app import App
from .matrix_client import MatrixClient from .matrix_client import MatrixClient, MatrixError
from .models.items import Account, Device, Event, Member, Room, Upload from .models.items import Account, Device, Event, Member, Room, Upload
from .models.model_store import ModelStore from .models.model_store import ModelStore
@ -51,7 +51,7 @@ class Backend:
password: str, password: str,
device_id: Optional[str] = None, device_id: Optional[str] = None,
homeserver: str = "https://matrix.org", homeserver: str = "https://matrix.org",
) -> Tuple[bool, str]: ) -> str:
client = MatrixClient( client = MatrixClient(
self, user=user, homeserver=homeserver, device_id=device_id, self, user=user, homeserver=homeserver, device_id=device_id,
@ -59,13 +59,13 @@ class Backend:
try: try:
await client.login(password) await client.login(password)
except RuntimeError as err: # XXX raise except MatrixError:
await client.close() await client.close()
return (False, err.args[0].message) raise
self.clients[client.user_id] = client self.clients[client.user_id] = client
self.models[Account][client.user_id] = Account(client.user_id) self.models[Account][client.user_id] = Account(client.user_id)
return (True, client.user_id) return client.user_id
async def resume_client(self, async def resume_client(self,

View File

@ -41,6 +41,8 @@ class MatrixError(Exception):
@classmethod @classmethod
def from_nio(cls, response: nio.ErrorResponse) -> "MatrixError": def from_nio(cls, response: nio.ErrorResponse) -> "MatrixError":
# Check for the M_CODE first: some errors for an API share the same
# http code, but have different M_CODEs (e.g. POST /login 403).
for subcls in cls.__subclasses__(): for subcls in cls.__subclasses__():
if subcls.m_code == response.status_code: if subcls.m_code == response.status_code:
return subcls() return subcls()
@ -58,6 +60,12 @@ class MatrixForbidden(MatrixError):
m_code: str = "M_FORBIDDEN" m_code: str = "M_FORBIDDEN"
@dataclass
class MatrixUserDeactivated(MatrixError):
http_code: int = 403
m_code: str = "M_USER_DEACTIVATED"
@dataclass @dataclass
class MatrixNotFound(MatrixError): class MatrixNotFound(MatrixError):
http_code: int = 404 http_code: int = 404
@ -159,7 +167,7 @@ class MatrixClient(nio.AsyncClient):
) )
if isinstance(response, nio.LoginError): if isinstance(response, nio.LoginError):
raise RuntimeError(response) raise MatrixError.from_nio(response)
asyncio.ensure_future(self.start()) asyncio.ensure_future(self.start())

View File

@ -34,23 +34,33 @@ HPage {
undefined, serverField.text, undefined, serverField.text,
] ]
py.callCoro("login_client", args, ([success, data]) => { loginTimeout.restart()
if (! success) {
errorMessage.text = qsTr(data) py.callCoro("login_client", args, userId => {
loginTimeout.stop()
errorMessage.text = ""
button.loading = false button.loading = false
return
}
py.callCoro( py.callCoro(
"saved_accounts." + "saved_accounts." +
(rememberAccount.checked ? "add": "delete"), (rememberAccount.checked ? "add": "delete"),
[data] [data]
) )
pageLoader.showPage( pageLoader.showPage(
"AccountSettings/AccountSettings", {userId: data} "AccountSettings/AccountSettings", {userId: data}
) )
}, type => {
loginTimeout.stop()
let txt = qsTr("Invalid request or login type")
errorMessage.text = "" if (type === "MatrixForbidden")
txt = qsTr("Invalid username or password")
if (type === "MatrixUserDeactivated")
txt = qsTr("This account was deactivated")
errorMessage.text = txt
button.loading = false button.loading = false
}) })
}, },
@ -58,6 +68,17 @@ HPage {
forgot: button => {} forgot: button => {}
}) })
Timer {
id: loginTimeout
interval: 30 * 1000
onTriggered: {
errorMessage.text = qsTr(
"This server seems unavailable. Verify your internet " +
"connection or try again in a few minutes."
)
}
}
HRowLayout { HRowLayout {
spacing: signInBox.horizontalSpacing * 1.25 spacing: signInBox.horizontalSpacing * 1.25
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter