[fractal/fractal-next] secret: Switch to libsecret
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] secret: Switch to libsecret
- Date: Fri, 25 Feb 2022 12:22:59 +0000 (UTC)
commit 60a0207ee2c0be3a4dd2e25f3918abd3c9ccb4fb
Author: Kévin Commaille <zecakeh tedomum fr>
Date: Mon Feb 14 21:53:11 2022 +0100
secret: Switch to libsecret
Cargo.lock | 367 ++++++-----------------------
Cargo.toml | 6 +-
build-aux/org.gnome.FractalNext.Devel.json | 1 -
data/resources/resources.gresource.xml | 1 +
data/resources/style.css | 3 +-
data/resources/ui/error-page.ui | 203 ++++++++++++++++
data/resources/ui/window.ui | 8 +
meson.build | 2 +
po/POTFILES.in | 2 +
src/error_page.rs | 133 +++++++++++
src/main.rs | 10 +-
src/secret.rs | 312 +++++++++++++++++-------
src/session/mod.rs | 53 +++--
src/user_facing_error.rs | 10 -
src/window.rs | 54 +++--
15 files changed, 722 insertions(+), 443 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index bb9e7eee3..72e1413e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,17 +23,6 @@ dependencies = [
"generic-array",
]
-[[package]]
-name = "aes"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
-dependencies = [
- "aes-soft",
- "aesni",
- "cipher 0.2.5",
-]
-
[[package]]
name = "aes"
version = "0.7.5"
@@ -41,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if 1.0.0",
- "cipher 0.3.0",
+ "cipher",
"cpufeatures",
"ctr",
"opaque-debug",
@@ -54,33 +43,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead",
- "aes 0.7.5",
- "cipher 0.3.0",
+ "aes",
+ "cipher",
"ctr",
"ghash",
"subtle",
]
-[[package]]
-name = "aes-soft"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug",
-]
-
-[[package]]
-name = "aesni"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug",
-]
-
[[package]]
name = "ahash"
version = "0.7.6"
@@ -149,7 +118,7 @@ version = "0.2.0-beta-1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0e317c257d4733c44475b3cefd53adb2540771ba8bd4adf37eabef3bbf8298e"
dependencies = [
- "enumflags2 0.7.3",
+ "enumflags2",
"futures",
"gdk4-wayland",
"gdk4-x11",
@@ -160,10 +129,10 @@ dependencies = [
"serde",
"serde_repr",
"tracing",
- "zbus 2.0.1",
- "zbus_macros 2.0.1",
- "zvariant 3.1.0",
- "zvariant_derive 3.1.0",
+ "zbus",
+ "zbus_macros",
+ "zvariant",
+ "zvariant_derive",
]
[[package]]
@@ -396,22 +365,6 @@ dependencies = [
"generic-array",
]
-[[package]]
-name = "block-modes"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
-dependencies = [
- "block-padding",
- "cipher 0.2.5",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
-
[[package]]
name = "bs58"
version = "0.4.0"
@@ -524,7 +477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91"
dependencies = [
"cfg-if 1.0.0",
- "cipher 0.3.0",
+ "cipher",
"cpufeatures",
"zeroize",
]
@@ -537,7 +490,7 @@ checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a"
dependencies = [
"aead",
"chacha20",
- "cipher 0.3.0",
+ "cipher",
"poly1305",
"zeroize",
]
@@ -560,15 +513,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "cipher"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
-dependencies = [
- "generic-array",
-]
-
[[package]]
name = "cipher"
version = "0.3.0"
@@ -727,23 +671,13 @@ dependencies = [
"generic-array",
]
-[[package]]
-name = "crypto-mac"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
-dependencies = [
- "generic-array",
- "subtle",
-]
-
[[package]]
name = "ctr"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
dependencies = [
- "cipher 0.3.0",
+ "cipher",
]
[[package]]
@@ -863,37 +797,16 @@ dependencies = [
"cfg-if 1.0.0",
]
-[[package]]
-name = "enumflags2"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
-dependencies = [
- "enumflags2_derive 0.6.4",
- "serde",
-]
-
[[package]]
name = "enumflags2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a25c90b056b3f84111cf183cbeddef0d3a0bbe9a674f057e1a1533c315f24def"
dependencies = [
- "enumflags2_derive 0.7.3",
+ "enumflags2_derive",
"serde",
]
-[[package]]
-name = "enumflags2_derive"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
-dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.14",
- "syn 1.0.85",
-]
-
[[package]]
name = "enumflags2_derive"
version = "0.7.3"
@@ -1014,6 +927,7 @@ dependencies = [
"image",
"indexmap",
"libadwaita",
+ "libsecret",
"log",
"matrix-sdk",
"mime",
@@ -1023,7 +937,6 @@ dependencies = [
"qrcode",
"rand 0.8.4",
"regex",
- "secret-service",
"serde",
"serde_json",
"sourceview5",
@@ -1429,9 +1342,9 @@ dependencies = [
[[package]]
name = "glib"
-version = "0.15.2"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30a3e6b2e5ef2ecfb10c1e083074a81160b8f6408fcc08195c872e9de37a361b"
+checksum = "41dcfbdb6cc6c02aee163339465d8a40d6f3f64c3a43f729a4195f0e153338b7"
dependencies = [
"bitflags",
"futures-channel",
@@ -1455,7 +1368,7 @@ checksum = "54c0c7194ee4c597b334e3ce84d22d929405e94497828e1c54da762cbe8e3d93"
dependencies = [
"anyhow",
"heck 0.4.0",
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro-error",
"proc-macro2 1.0.36",
"quote 1.0.14",
@@ -1714,9 +1627,9 @@ checksum = "da5bf7748fd4cd0b2490df8debcc911809dbcbee4ece9531b96c29a9c729de5a"
[[package]]
name = "gtk4"
-version = "0.4.4"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5020aeb559e0431930d66d85b8f16fc453fc0863466b13b7e1e1b800cf1a47b"
+checksum = "9e841556e3fe55d8a43ada76b7b08a5f65570bbdfe3b8f72c333053b8832c626"
dependencies = [
"bitflags",
"cairo-rs",
@@ -1742,7 +1655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573db42bb64973a4d5f718b73caa7204285a1a665308a23b11723d0ee56ec305"
dependencies = [
"anyhow",
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro-error",
"proc-macro2 1.0.36",
"quote 1.0.14",
@@ -1826,26 +1739,6 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-[[package]]
-name = "hkdf"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
-dependencies = [
- "digest 0.9.0",
- "hmac 0.10.1",
-]
-
-[[package]]
-name = "hmac"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
-dependencies = [
- "crypto-mac",
- "digest 0.9.0",
-]
-
[[package]]
name = "hmac"
version = "0.12.0"
@@ -2151,6 +2044,34 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "libsecret"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b8d814edb0cb306ffded3f1bfe72d6689529f95f7313a718331802723a73e5a"
+dependencies = [
+ "bitflags",
+ "gio",
+ "glib",
+ "libc",
+ "libsecret-sys",
+ "once_cell",
+]
+
+[[package]]
+name = "libsecret-sys"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "287d2a0fcd95e4d7b0ac6fc9f802691a790d7e522138713b0cacebc4e63cab91"
+dependencies = [
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+ "system-deps 6.0.0",
+]
+
[[package]]
name = "libspa"
version = "0.4.1"
@@ -2343,7 +2264,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
- "hmac 0.12.0",
+ "hmac",
"lru 0.7.2",
"matrix-sdk-common",
"matrix-sdk-crypto",
@@ -2383,7 +2304,7 @@ name = "matrix-sdk-crypto"
version = "0.4.1"
source =
"git+https://github.com/jsparber/matrix-rust-sdk.git?branch=enable_ruma_unstable_pre_spec#0dd623970bb1927db3c8d187f26c42cdfaf21bcc"
dependencies = [
- "aes 0.7.5",
+ "aes",
"aes-gcm",
"atomic",
"base64",
@@ -2392,7 +2313,7 @@ dependencies = [
"dashmap",
"futures-util",
"getrandom 0.2.4",
- "hmac 0.12.0",
+ "hmac",
"matrix-qrcode",
"matrix-sdk-common",
"olm-rs",
@@ -2510,16 +2431,6 @@ dependencies = [
"tempfile",
]
-[[package]]
-name = "nb-connect"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15"
-dependencies = [
- "libc",
- "socket2",
-]
-
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
@@ -2539,19 +2450,6 @@ dependencies = [
"void",
]
-[[package]]
-name = "nix"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 0.1.10",
- "libc",
- "void",
-]
-
[[package]]
name = "nix"
version = "0.23.1"
@@ -2598,40 +2496,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "num"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
-dependencies = [
- "num-bigint",
- "num-complex",
- "num-integer",
- "num-iter",
- "num-rational 0.3.2",
- "num-traits",
-]
-
-[[package]]
-name = "num-bigint"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
-dependencies = [
- "num-traits",
-]
-
[[package]]
name = "num-integer"
version = "0.1.44"
@@ -2660,7 +2524,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
- "num-bigint",
"num-integer",
"num-traits",
]
@@ -2710,7 +2573,7 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"syn 1.0.85",
@@ -3085,15 +2948,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131"
-[[package]]
-name = "proc-macro-crate"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
-dependencies = [
- "toml",
-]
-
[[package]]
name = "proc-macro-crate"
version = "1.1.0"
@@ -3429,7 +3283,7 @@ name = "ruma-api-macros"
version = "0.18.5"
source =
"git+https://github.com/ruma/ruma/?rev=b9f32bc6327542d382d4eb42ec43623495c50e66#b9f32bc6327542d382d4eb42ec43623495c50e66"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"syn 1.0.85",
@@ -3493,7 +3347,7 @@ name = "ruma-events-macros"
version = "0.24.6"
source =
"git+https://github.com/ruma/ruma/?rev=b9f32bc6327542d382d4eb42ec43623495c50e66#b9f32bc6327542d382d4eb42ec43623495c50e66"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"syn 1.0.85",
@@ -3567,7 +3421,7 @@ name = "ruma-serde-macros"
version = "0.5.0"
source =
"git+https://github.com/ruma/ruma/?rev=b9f32bc6327542d382d4eb42ec43623495c50e66#b9f32bc6327542d382d4eb42ec43623495c50e66"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"syn 1.0.85",
@@ -3638,12 +3492,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "scoped-tls"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
-
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
@@ -3656,26 +3504,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-[[package]]
-name = "secret-service"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec"
-dependencies = [
- "aes 0.6.0",
- "block-modes",
- "hkdf",
- "lazy_static",
- "num",
- "rand 0.8.4",
- "serde",
- "sha2 0.9.9",
- "zbus 1.9.1",
- "zbus_macros 1.9.1",
- "zvariant 2.10.0",
- "zvariant_derive 2.10.0",
-]
-
[[package]]
name = "security-framework"
version = "2.5.0"
@@ -3893,11 +3721,13 @@ dependencies = [
[[package]]
name = "sourceview5"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5c1e4191e6387d0542caf6761c9c101e4648cb588b965f8efec8a3943a1ad22"
+checksum = "ec66e5db143023da4dbe7dcb5f9d7bb50c0e5668c3ea91d40e8ba188f7f07a54"
dependencies = [
"bitflags",
+ "futures-channel",
+ "futures-core",
"gdk-pixbuf",
"gdk4",
"gio",
@@ -3910,9 +3740,9 @@ dependencies = [
[[package]]
name = "sourceview5-sys"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900965718bc3384c7d3f08976b35b47810ee73810b2882d30453b33ba7622337"
+checksum = "6bbf0b30cd67340b8fc695f460859dbadaec159850c260a0f766cc607bb14a86"
dependencies = [
"gdk-pixbuf-sys",
"gdk4-sys",
@@ -4644,29 +4474,6 @@ dependencies = [
"time",
]
-[[package]]
-name = "zbus"
-version = "1.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad"
-dependencies = [
- "async-io",
- "byteorder",
- "derivative",
- "enumflags2 0.6.4",
- "fastrand",
- "futures",
- "nb-connect",
- "nix 0.17.0",
- "once_cell",
- "polling",
- "scoped-tls",
- "serde",
- "serde_repr",
- "zbus_macros 1.9.1",
- "zvariant 2.10.0",
-]
-
[[package]]
name = "zbus"
version = "2.0.1"
@@ -4683,7 +4490,7 @@ dependencies = [
"async-trait",
"byteorder",
"derivative",
- "enumflags2 0.7.3",
+ "enumflags2",
"event-listener",
"futures-core",
"futures-sink",
@@ -4697,21 +4504,9 @@ dependencies = [
"serde_repr",
"sha1",
"static_assertions",
- "zbus_macros 2.0.1",
+ "zbus_macros",
"zbus_names",
- "zvariant 3.1.0",
-]
-
-[[package]]
-name = "zbus_macros"
-version = "1.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93"
-dependencies = [
- "proc-macro-crate 0.1.5",
- "proc-macro2 1.0.36",
- "quote 1.0.14",
- "syn 1.0.85",
+ "zvariant",
]
[[package]]
@@ -4720,7 +4515,7 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e03af45fc15e2c977161c5ffea56c43c41f425a963affd7074bf91b5bf5a8cf"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"regex",
@@ -4735,7 +4530,7 @@ checksum = "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1"
dependencies = [
"serde",
"static_assertions",
- "zvariant 3.1.0",
+ "zvariant",
]
[[package]]
@@ -4759,20 +4554,6 @@ dependencies = [
"synstructure",
]
-[[package]]
-name = "zvariant"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525"
-dependencies = [
- "byteorder",
- "enumflags2 0.6.4",
- "libc",
- "serde",
- "static_assertions",
- "zvariant_derive 2.10.0",
-]
-
[[package]]
name = "zvariant"
version = "3.1.0"
@@ -4780,23 +4561,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb31b009e0b0c4f2c1283c9c23129e4f76020da4b3c4dfa032abfbfe30a2c02"
dependencies = [
"byteorder",
- "enumflags2 0.7.3",
+ "enumflags2",
"libc",
"serde",
"static_assertions",
- "zvariant_derive 3.1.0",
-]
-
-[[package]]
-name = "zvariant_derive"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9"
-dependencies = [
- "proc-macro-crate 1.1.0",
- "proc-macro2 1.0.36",
- "quote 1.0.14",
- "syn 1.0.85",
+ "zvariant_derive",
]
[[package]]
@@ -4805,7 +4574,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5295bdc2688c7239423889191d730ad071f814dc36c48edf7cda23f38dd28b2a"
dependencies = [
- "proc-macro-crate 1.1.0",
+ "proc-macro-crate",
"proc-macro2 1.0.36",
"quote 1.0.14",
"syn 1.0.85",
diff --git a/Cargo.toml b/Cargo.toml
index a0068d40e..ce24394ad 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,7 @@ serde = "1.0.130"
serde_json = "1.0"
tokio = { version = "1.15", features = ["rt", "rt-multi-thread", "sync"] }
url = "2.2"
-secret-service = "2.0"
+libsecret = { version = "0.1.3", features = ["v0_19"] }
html2pango = "0.4"
futures = "0.3"
rand = "0.8"
@@ -47,11 +47,11 @@ num_enum = "0.5.6"
[dependencies.sourceview]
package = "sourceview5"
-version = "0.4.0"
+version = "0.4.1"
[dependencies.gtk]
package = "gtk4"
-version = "0.4.4"
+version = "0.4.6"
features = ["v4_6"]
[dependencies.adw]
diff --git a/build-aux/org.gnome.FractalNext.Devel.json b/build-aux/org.gnome.FractalNext.Devel.json
index 0f44223b8..0ec20c56c 100644
--- a/build-aux/org.gnome.FractalNext.Devel.json
+++ b/build-aux/org.gnome.FractalNext.Devel.json
@@ -15,7 +15,6 @@
"--share=network",
"--share=ipc",
"--device=dri",
- "--talk-name=org.freedesktop.secrets",
"--env=RUST_LOG=fractal=debug",
"--env=G_MESSAGES_DEBUG=none",
"--env=RUST_BACKTRACE=1"
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index fd9dd2e6b..766d01c7b 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -58,6 +58,7 @@
<file compressed="true" preprocess="xml-stripblanks"
alias="content-verification-info-bar.ui">ui/content-verification-info-bar.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="content.ui">ui/content.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="context-menu-bin.ui">ui/context-menu-bin.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="error-page.ui">ui/error-page.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="event-menu.ui">ui/event-menu.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="event-source-dialog.ui">ui/event-source-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="greeter.ui">ui/greeter.ui</file>
diff --git a/data/resources/style.css b/data/resources/style.css
index ba84a43c0..f6ce190a9 100644
--- a/data/resources/style.css
+++ b/data/resources/style.css
@@ -44,7 +44,8 @@ button.opaque.success {
color: @error_bg_color;
}
-preferencesgroup .body {
+preferencesgroup .body,
+.large-line-height {
line-height: 140%;
}
diff --git a/data/resources/ui/error-page.ui b/data/resources/ui/error-page.ui
new file mode 100644
index 000000000..bc1e5f818
--- /dev/null
+++ b/data/resources/ui/error-page.ui
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="ErrorPage" parent="AdwBin">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHeaderBar">
+ <property name="title-widget">
+ <object class="AdwWindowTitle">
+ <property name="title">Error</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage" id="page">
+ <property name="title">Secret Service Error</property>
+ <property name="icon-name">dialog-password-symbolic</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="AdwClamp">
+ <child>
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">secret-error-session</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">It seems like one of the Fractal
sessions stored in the Secret Service is corrupted. If you know how to fix it you should do so.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Alternatively, we could delete
this session for you. This means you will have to login again and you will lose access to your encrypted
messages, unless you have a session open in another client or you have already backed up your encryption
keys.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <style>
+ <class name="warning"/>
+ </style>
+ <property name="halign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Clicking this button might
delete more than one session!</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <style>
+ <class name="destructive-action"/>
+ <class name="pill"/>
+ </style>
+ <property name="halign">center</property>
+ <property name="label" translatable="yes">Delete the corrupted
session</property>
+ <property
name="action-name">error-page.remove-secret-error-session</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">secret-error-other</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Fractal relies on a Secret Service
Provider to manage your sensitive session information and an error occurred while we where trying to store or
get your session.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Here are a few things that
might help you fix issues with the Secret Service:</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="valign">start</property>
+ <property name="label">•</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Make sure you have a
Secret Service Provider installed, like gnome-keyring.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="valign">start</property>
+ <property name="label">•</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Check that you have a
default keyring and that is is unlocked.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <style>
+ <class name="large-line-height"/>
+ </style>
+ <property name="wrap">true</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Check the application logs and
your distribution's documentation for more details.</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/resources/ui/window.ui b/data/resources/ui/window.ui
index 372ffccda..851e4364e 100644
--- a/data/resources/ui/window.ui
+++ b/data/resources/ui/window.ui
@@ -57,6 +57,14 @@
<property name="transition-type">crossfade</property>
</object>
</child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">error-page</property>
+ <property name="child">
+ <object class="ErrorPage" id="error_page"/>
+ </property>
+ </object>
+ </child>
</object>
</child>
</object>
diff --git a/meson.build b/meson.build
index af0a9ce4d..315311b86 100644
--- a/meson.build
+++ b/meson.build
@@ -26,6 +26,8 @@ dependency('gstreamer-1.0', version: '>= 1.18')
dependency('gstreamer-base-1.0', version: '>= 1.18')
dependency('gstreamer-plugins-base-1.0', version: '>= 1.18')
dependency('gstreamer-video-1.0', version: '>= 1.18')
+dependency('libsecret-1', version: '>= 0.19',
+ default_options: ['gtk_doc=false', 'gir=false', 'vapi=false'])
glib_compile_resources = find_program('glib-compile-resources', required: true)
glib_compile_schemas = find_program('glib-compile-schemas', required: true)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5ac240a4b..84f604743 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,6 +24,7 @@ data/resources/ui/content-room-history.ui
data/resources/ui/content-state-creation.ui
data/resources/ui/content-state-tombstone.ui
data/resources/ui/content.ui
+data/resources/ui/error-page.ui
data/resources/ui/event-menu.ui
data/resources/ui/event-source-dialog.ui
data/resources/ui/greeter.ui
@@ -41,6 +42,7 @@ data/resources/ui/qr-code-scanner.ui
# Rust files
src/application.rs
src/components/editable_avatar.rs
+src/error_page.rs
src/login.rs
src/secret.rs
src/session/account_settings/devices_page/device_list.rs
diff --git a/src/error_page.rs b/src/error_page.rs
new file mode 100644
index 000000000..7ada187fb
--- /dev/null
+++ b/src/error_page.rs
@@ -0,0 +1,133 @@
+use adw::subclass::prelude::BinImpl;
+use gettextrs::gettext;
+use gtk::{self, glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
+use log::error;
+
+use crate::{components::Toast, secret, secret::SecretError, spawn, window::Window};
+
+pub enum ErrorSubpage {
+ SecretErrorSession,
+ SecretErrorOther,
+}
+
+impl AsRef<str> for ErrorSubpage {
+ fn as_ref(&self) -> &str {
+ match self {
+ Self::SecretErrorSession => "secret-error-session",
+ Self::SecretErrorOther => "secret-error-other",
+ }
+ }
+}
+
+mod imp {
+ use std::cell::RefCell;
+
+ use glib::subclass::InitializingObject;
+
+ use super::*;
+
+ #[derive(Debug, Default, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/error-page.ui")]
+ pub struct ErrorPage {
+ #[template_child]
+ pub page: TemplateChild<adw::StatusPage>,
+ #[template_child]
+ pub stack: TemplateChild<gtk::Stack>,
+ pub secret_error: RefCell<Option<SecretError>>,
+ }
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for ErrorPage {
+ const NAME: &'static str = "ErrorPage";
+ type Type = super::ErrorPage;
+ type ParentType = adw::Bin;
+
+ fn class_init(klass: &mut Self::Class) {
+ Self::bind_template(klass);
+ klass.set_accessible_role(gtk::AccessibleRole::Group);
+ klass.install_action(
+ "error-page.remove-secret-error-session",
+ None,
+ |obj, _, _| {
+ spawn!(clone!(@weak obj => async move {
+ obj.remove_secret_error_session().await;
+ }));
+ },
+ );
+ }
+
+ fn instance_init(obj: &InitializingObject<Self>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for ErrorPage {
+ fn constructed(&self, obj: &Self::Type) {
+ obj.action_set_enabled("error-page.remove-secret-error-session", false);
+ }
+ }
+
+ impl WidgetImpl for ErrorPage {}
+
+ impl BinImpl for ErrorPage {}
+}
+
+glib::wrapper! {
+ pub struct ErrorPage(ObjectSubclass<imp::ErrorPage>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl ErrorPage {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create ErrorPage")
+ }
+
+ pub fn display_secret_error(&self, message: &str, error: SecretError) {
+ let priv_ = self.imp();
+ self.action_set_enabled(
+ "error-page.remove-secret-error-session",
+ matches!(error, SecretError::CorruptSession(_)),
+ );
+ priv_.page.set_description(Some(message));
+ priv_
+ .stack
+ .set_visible_child_name(error.error_subpage().as_ref());
+ priv_.secret_error.replace(Some(error));
+ }
+
+ async fn remove_secret_error_session(&self) {
+ if let Some(SecretError::CorruptSession((_, item))) = self.imp().secret_error.take() {
+ match secret::remove_item(&item).await {
+ Ok(_) => {
+ self.action_set_enabled("error-page.remove-secret-error-session", false);
+ if let Some(window) = self
+ .root()
+ .as_ref()
+ .and_then(|root| root.downcast_ref::<Window>())
+ {
+ window.add_toast(&Toast::new(&gettext("Session removed successfully.")));
+ window.restore_sessions().await;
+ }
+ }
+ Err(err) => {
+ error!("Could not remove session from secret storage: {:?}", err);
+ if let Some(window) = self
+ .root()
+ .as_ref()
+ .and_then(|root| root.downcast_ref::<Window>())
+ {
+ window.add_toast(&Toast::new(&gettext(
+ "Could not remove session from secret storage",
+ )));
+ }
+ }
+ }
+ }
+ }
+}
+
+impl Default for ErrorPage {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 9dd0791fa..72577f0f6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,6 +9,7 @@ mod prelude;
mod components;
mod contrib;
+mod error_page;
mod greeter;
mod login;
mod login_advanced_dialog;
@@ -24,8 +25,13 @@ use gtk::{gdk::Display, gio, IconTheme};
use once_cell::sync::Lazy;
use self::{
- application::Application, greeter::Greeter, login::Login, session::Session,
- user_facing_error::UserFacingError, window::Window,
+ application::Application,
+ error_page::{ErrorPage, ErrorSubpage},
+ greeter::Greeter,
+ login::Login,
+ session::Session,
+ user_facing_error::UserFacingError,
+ window::Window,
};
/// The default tokio runtime to be used for async tasks
diff --git a/src/secret.rs b/src/secret.rs
index f504676a2..5ec64dee1 100644
--- a/src/secret.rs
+++ b/src/secret.rs
@@ -1,13 +1,66 @@
-use std::{path::PathBuf, string::FromUtf8Error};
+use std::{collections::HashMap, fmt, path::PathBuf, string::FromUtf8Error};
use gettextrs::gettext;
+use gtk::glib;
+use libsecret::{
+ password_clear_future, password_search_future, password_store_binary_future, prelude::*,
+ Retrievable, Schema, SchemaAttributeType, SchemaFlags, SearchFlags, Value, COLLECTION_DEFAULT,
+};
+use log::error;
use matrix_sdk::ruma::identifiers::{DeviceId, UserId};
-use secret_service::{EncryptionType, SecretService};
use serde::{Deserialize, Serialize};
use serde_json::error::Error as JsonError;
use url::Url;
-use crate::config::APP_ID;
+use crate::{config::APP_ID, ErrorSubpage};
+
+/// Any error that can happen when interacting with the secret service.
+#[derive(Debug, Clone)]
+pub enum SecretError {
+ CorruptSession((String, Retrievable)),
+ Libsecret(glib::Error),
+ Unknown,
+}
+
+impl SecretError {
+ /// Get the error subpage that matches `self`.
+ pub fn error_subpage(&self) -> ErrorSubpage {
+ match self {
+ Self::CorruptSession(_) => ErrorSubpage::SecretErrorSession,
+ _ => ErrorSubpage::SecretErrorOther,
+ }
+ }
+}
+
+impl From<glib::Error> for SecretError {
+ fn from(error: glib::Error) -> Self {
+ Self::Libsecret(error)
+ }
+}
+
+impl fmt::Display for SecretError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::CorruptSession((message, _)) => message.to_owned(),
+ Self::Libsecret(error) if error.is::<libsecret::Error>() => {
+ match error.kind::<libsecret::Error>() {
+ Some(libsecret::Error::Protocol) => error.message().to_owned(),
+ Some(libsecret::Error::IsLocked) => {
+ gettext("Could not unlock the secret storage")
+ }
+ _ => gettext(
+ "An unknown error occurred when interacting with the secret storage",
+ ),
+ }
+ }
+ _ => gettext("An unknown error occurred when interacting with the secret storage"),
+ }
+ )
+ }
+}
#[derive(Debug, Clone)]
pub struct StoredSession {
@@ -18,7 +71,125 @@ pub struct StoredSession {
pub secret: Secret,
}
+impl StoredSession {
+ /// Build self from a secret.
+ pub async fn try_from_secret_item(item: Retrievable) -> Result<Self, SecretError> {
+ let attr = item.attributes();
+
+ let homeserver = match attr.get("homeserver") {
+ Some(string) => match Url::parse(string) {
+ Ok(homeserver) => homeserver,
+ Err(err) => {
+ error!(
+ "Could not parse 'homeserver' attribute in stored session: {:?}",
+ err
+ );
+ return Err(SecretError::CorruptSession((
+ gettext("Malformed homeserver in stored session"),
+ item,
+ )));
+ }
+ },
+ None => {
+ return Err(SecretError::CorruptSession((
+ gettext("Could not find homeserver in stored session"),
+ item,
+ )));
+ }
+ };
+ let user_id = match attr.get("user") {
+ Some(string) => match UserId::parse(string.as_str()) {
+ Ok(user_id) => user_id,
+ Err(err) => {
+ error!(
+ "Could not parse 'user' attribute in stored session: {:?}",
+ err
+ );
+ return Err(SecretError::CorruptSession((
+ gettext("Malformed user ID in stored session"),
+ item,
+ )));
+ }
+ },
+ None => {
+ return Err(SecretError::CorruptSession((
+ gettext("Could not find user ID in stored session"),
+ item,
+ )));
+ }
+ };
+ let device_id = match attr.get("device-id") {
+ Some(string) => <&DeviceId>::from(string.as_str()).to_owned(),
+ None => {
+ return Err(SecretError::CorruptSession((
+ gettext("Could not find device ID in stored session"),
+ item,
+ )));
+ }
+ };
+ let path = match attr.get("db-path") {
+ Some(string) => PathBuf::from(string),
+ None => {
+ return Err(SecretError::CorruptSession((
+ gettext("Could not find database path in stored session"),
+ item,
+ )));
+ }
+ };
+ let secret = match item.retrieve_secret_future().await {
+ Ok(Some(value)) => match Secret::from_utf8(value.get()) {
+ Ok(secret) => secret,
+ Err(err) => {
+ error!("Could not parse secret in stored session: {:?}", err);
+ return Err(SecretError::CorruptSession((
+ gettext("Malformed secret in stored session"),
+ item,
+ )));
+ }
+ },
+ Ok(None) => {
+ return Err(SecretError::CorruptSession((
+ gettext("No secret in stored session"),
+ item,
+ )));
+ }
+ Err(err) => {
+ error!("Could not get secret in stored session: {:?}", err);
+ return Err(SecretError::CorruptSession((
+ gettext("Could not get secret in stored session"),
+ item,
+ )));
+ }
+ };
+
+ Ok(Self {
+ homeserver,
+ user_id,
+ device_id,
+ path,
+ secret,
+ })
+ }
+
+ /// Build a secret from `self`.
+ ///
+ /// Returns an (attributes, secret) tuple.
+ pub fn to_secret_item(&self) -> (HashMap<&str, &str>, Value) {
+ let attributes = HashMap::from([
+ ("homeserver", self.homeserver.as_str()),
+ ("user", self.user_id.as_str()),
+ ("device-id", self.device_id.as_str()),
+ ("db-path", self.path.to_str().unwrap()),
+ ]);
+
+ let secret = Value::new(&self.secret.to_string(), "application/json");
+
+ (attributes, secret)
+ }
+}
+
/// A possible error value when converting a `Secret` from a UTF-8 byte vector.
+#[derive(Debug)]
pub enum FromUtf8SecretError {
Str(FromUtf8Error),
Json(JsonError),
@@ -44,11 +215,6 @@ pub struct Secret {
}
impl Secret {
- /// Returns a byte vec of this `Secret`’s contents.
- pub fn as_bytes(&self) -> Vec<u8> {
- serde_json::to_string(self).unwrap().as_bytes().to_vec()
- }
-
/// Converts a vector of bytes to a `Secret`.
pub fn from_utf8(vec: Vec<u8>) -> Result<Self, FromUtf8SecretError> {
let s = String::from_utf8(vec)?;
@@ -56,101 +222,77 @@ impl Secret {
}
}
+impl fmt::Display for Secret {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", serde_json::to_string(self).unwrap())
+ }
+}
+
+/// The `Schema` of the items in the `SecretService`.
+fn schema() -> Schema {
+ let attributes = HashMap::from([
+ ("homeserver", SchemaAttributeType::String),
+ ("user", SchemaAttributeType::String),
+ ("device-id", SchemaAttributeType::String),
+ ("db-path", SchemaAttributeType::String),
+ ]);
+
+ Schema::new(APP_ID, SchemaFlags::NONE, attributes)
+}
+
/// Retrieves all sessions stored to the `SecretService`
-pub fn restore_sessions() -> Result<Vec<StoredSession>, secret_service::Error> {
- let ss = SecretService::new(EncryptionType::Dh)?;
- let collection = get_default_collection_unlocked(&ss)?;
-
- // Sessions that contain or produce errors are ignored.
- // TODO: Return error for corrupt sessions
-
- let res = collection
- .search_items([("xdg:schema", APP_ID)].into())?
- .iter()
- .filter_map(|item| {
- let attr = item.get_attributes().ok()?;
-
- let homeserver = Url::parse(attr.get("homeserver")?).ok()?;
- let user_id = UserId::parse(attr.get("user")?.as_str()).ok()?;
- let device_id = <&DeviceId>::from(attr.get("device-id")?.as_str()).to_owned();
- let path = PathBuf::from(attr.get("db-path")?);
- let secret = Secret::from_utf8(item.get_secret().ok()?).ok()?;
-
- Some(StoredSession {
- homeserver,
- path,
- user_id,
- device_id,
- secret,
- })
- })
- .collect();
+pub async fn restore_sessions() -> Result<Vec<StoredSession>, SecretError> {
+ let items = password_search_future(
+ Some(&schema()),
+ HashMap::new(),
+ SearchFlags::ALL | SearchFlags::UNLOCK | SearchFlags::LOAD_SECRETS,
+ )
+ .await?;
+ let mut sessions = Vec::with_capacity(items.len());
+
+ for item in items {
+ sessions.push(StoredSession::try_from_secret_item(item).await?);
+ }
- Ok(res)
+ Ok(sessions)
}
/// Writes a session to the `SecretService`, overwriting any previously stored
/// session with the same `homeserver`, `username` and `device-id`.
-pub fn store_session(session: &StoredSession) -> Result<(), secret_service::Error> {
- let ss = SecretService::new(EncryptionType::Dh)?;
- let collection = get_default_collection_unlocked(&ss)?;
-
- let attributes = [
- ("xdg:schema", APP_ID),
- ("homeserver", session.homeserver.as_str()),
- ("user", session.user_id.as_str()),
- ("device-id", session.device_id.as_str()),
- ("db-path", session.path.to_str().unwrap()),
- ]
- .into();
-
- collection.create_item(
+pub async fn store_session(session: &StoredSession) -> Result<(), SecretError> {
+ let (attributes, secret) = session.to_secret_item();
+
+ password_store_binary_future(
+ Some(&schema()),
+ attributes,
+ Some(&COLLECTION_DEFAULT),
// Translators: The parameter is a Matrix User ID
&gettext!("Fractal: Matrix credentials for {}", session.user_id),
- attributes,
- &session.secret.as_bytes(),
- true,
- "application/json",
- )?;
+ &secret,
+ )
+ .await?;
Ok(())
}
/// Removes a session from the `SecretService`
-pub fn remove_session(session: &StoredSession) -> Result<(), secret_service::Error> {
- let ss = SecretService::new(EncryptionType::Dh)?;
- let collection = get_default_collection_unlocked(&ss)?;
-
- let attributes = [
- ("xdg:schema", APP_ID),
- ("homeserver", session.homeserver.as_str()),
- ("user", session.user_id.as_str()),
- ("device-id", session.device_id.as_str()),
- ("db-path", session.path.to_str().unwrap()),
- ]
- .into();
+pub async fn remove_session(session: &StoredSession) -> Result<(), SecretError> {
+ let (attributes, _) = session.to_secret_item();
- let items = collection.search_items(attributes)?;
-
- for item in items {
- item.delete()?;
- }
+ password_clear_future(Some(&schema()), attributes).await?;
Ok(())
}
-fn get_default_collection_unlocked<'a>(
- secret_service: &'a SecretService,
-) -> Result<secret_service::Collection<'a>, secret_service::Error> {
- let collection = match secret_service.get_default_collection() {
- Ok(col) => col,
- Err(secret_service::Error::NoResult) => {
- secret_service.create_collection("default", "default")?
- }
- Err(error) => return Err(error),
- };
+/// Removes an item from the `SecretService`
+pub async fn remove_item(item: &Retrievable) -> Result<(), SecretError> {
+ let attributes = item.attributes();
+ let mut attr = HashMap::with_capacity(attributes.len());
- collection.unlock()?;
+ for (key, value) in attributes.iter() {
+ attr.insert(key.as_str(), value.as_str());
+ }
+ password_clear_future(Some(&schema()), attr).await?;
- Ok(collection)
+ Ok(())
}
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 3665442c9..dda550163 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -127,7 +127,7 @@ mod imp {
klass.install_action("session.logout", None, move |session, _, _| {
spawn!(clone!(@weak session => async move {
session.imp().logout_on_dispose.set(false);
- session.logout().await
+ session.logout(true).await
}));
});
@@ -248,7 +248,7 @@ mod imp {
}
if self.logout_on_dispose.get() {
- glib::MainContext::default().block_on(obj.logout());
+ glib::MainContext::default().block_on(obj.logout(true));
}
}
}
@@ -347,7 +347,7 @@ impl Session {
spawn!(
glib::PRIORITY_DEFAULT_IDLE,
clone!(@weak self as obj => async move {
- obj.handle_login_result(handle.await.unwrap(), true);
+ obj.handle_login_result(handle.await.unwrap(), true).await;
})
);
}
@@ -381,12 +381,12 @@ impl Session {
spawn!(
glib::PRIORITY_DEFAULT_IDLE,
clone!(@weak self as obj => async move {
- obj.handle_login_result(handle.await.unwrap(), false);
+ obj.handle_login_result(handle.await.unwrap(), false).await;
})
);
}
- fn handle_login_result(
+ async fn handle_login_result(
&self,
result: Result<(Client, StoredSession), matrix_sdk::Error>,
store_session: bool,
@@ -401,19 +401,19 @@ impl Session {
self.update_user_profile();
- let res = if store_session {
- match secret::store_session(&session) {
- Ok(()) => None,
- Err(error) => {
- warn!("Couldn't store session: {:?}", error);
- Some(Toast::new(&gettext!(
- "Unable to store session: {}",
- &error.to_user_facing()
- )))
+ if store_session {
+ if let Err(error) = secret::store_session(&session).await {
+ warn!("Couldn't store session: {:?}", error);
+ if let Some(window) = self.parent_window() {
+ window.switch_to_error_page(
+ &gettext!("Unable to store session: {}", error),
+ error,
+ );
}
+ self.logout(false).await;
+ fs::remove_dir_all(session.path).unwrap();
+ return;
}
- } else {
- None
};
priv_.info.set(session).unwrap();
@@ -422,7 +422,7 @@ impl Session {
self.sync();
- res
+ None
}
Err(error) => {
error!("Failed to prepare the session: {}", error);
@@ -686,7 +686,7 @@ impl Session {
window.show();
}
- pub async fn logout(&self) {
+ pub async fn logout(&self, cleanup: bool) {
let stack = &self.imp().stack;
self.emit_by_name::<()>("logged-out", &[]);
@@ -704,7 +704,11 @@ impl Session {
});
match handle.await.unwrap() {
- Ok(_) => self.cleanup_session(),
+ Ok(_) => {
+ if cleanup {
+ self.cleanup_session().await
+ }
+ }
Err(error) => {
error!("Couldn’t logout the session {}", error);
if let Some(window) = self.parent_window() {
@@ -720,10 +724,15 @@ impl Session {
/// `Session::logout`.
pub fn handle_logged_out(&self) {
self.emit_by_name::<()>("logged-out", &[]);
- self.cleanup_session();
+ spawn!(
+ glib::PRIORITY_LOW,
+ clone!(@strong self as obj => async move {
+ obj.cleanup_session().await;
+ })
+ );
}
- fn cleanup_session(&self) {
+ async fn cleanup_session(&self) {
let priv_ = self.imp();
let info = priv_.info.get().unwrap();
@@ -737,7 +746,7 @@ impl Session {
handle.abort();
}
- if let Err(error) = secret::remove_session(info) {
+ if let Err(error) = secret::remove_session(info).await {
error!(
"Failed to remove credentials from SecretService after logout: {}",
error
diff --git a/src/user_facing_error.rs b/src/user_facing_error.rs
index c07bed1ca..1b0162cd4 100644
--- a/src/user_facing_error.rs
+++ b/src/user_facing_error.rs
@@ -57,13 +57,3 @@ impl UserFacingError for Error {
}
}
}
-
-impl UserFacingError for secret_service::Error {
- fn to_user_facing(self) -> String {
- use secret_service::Error::*;
- match self {
- Locked => gettext("Keychain locked."),
- _ => gettext("Secret Service error."),
- }
- }
-}
diff --git a/src/window.rs b/src/window.rs
index fcdddfa15..35edf1859 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -7,7 +7,8 @@ use log::warn;
use crate::{
components::{InAppNotification, Toast},
config::{APP_ID, PROFILE},
- secret, Application, Greeter, Login, Session, UserFacingError,
+ secret::{self, SecretError},
+ spawn, Application, ErrorPage, Greeter, Login, Session,
};
mod imp {
@@ -28,6 +29,8 @@ mod imp {
#[template_child]
pub login: TemplateChild<Login>,
#[template_child]
+ pub error_page: TemplateChild<ErrorPage>,
+ #[template_child]
pub sessions: TemplateChild<gtk::Stack>,
#[template_child]
pub error_list: TemplateChild<gio::ListStore>,
@@ -85,19 +88,6 @@ mod imp {
}
obj.load_window_size();
- obj.restore_sessions();
-
- self.login
- .connect_new_session(clone!(@weak obj => move |_login, session| {
- obj.add_session(&session);
- obj.switch_to_loading_page();
- }));
-
- self.main_stack.connect_visible_child_notify(
- clone!(@weak obj => move |_| obj.set_default_by_child()),
- );
-
- obj.set_default_by_child();
// Ask for the toggle fullscreen state
let fullscreen = gio::SimpleAction::new("toggle-fullscreen", None);
@@ -109,6 +99,10 @@ mod imp {
}
}));
obj.add_action(&fullscreen);
+
+ spawn!(clone!(@weak obj => async move {
+ obj.restore_sessions().await;
+ }));
}
}
@@ -170,8 +164,8 @@ impl Window {
}
}
- fn restore_sessions(&self) {
- match secret::restore_sessions() {
+ pub async fn restore_sessions(&self) {
+ match secret::restore_sessions().await {
Ok(sessions) => {
if sessions.is_empty() {
self.switch_to_greeter_page(false);
@@ -182,13 +176,27 @@ impl Window {
self.add_session(&session);
}
}
+
+ let priv_ = self.imp();
+ priv_.login.connect_new_session(
+ clone!(@weak self as obj => move |_login, session| {
+ obj.add_session(&session);
+ obj.switch_to_loading_page();
+ }),
+ );
+
+ priv_.main_stack.connect_visible_child_notify(
+ clone!(@weak self as obj => move |_| obj.set_default_by_child()),
+ );
+
+ self.set_default_by_child();
}
Err(error) => {
warn!("Failed to restore previous sessions: {:?}", error);
- self.add_toast(&Toast::new(&gettext!(
- "Unable to restore previous sessions: {}",
- &error.to_user_facing()
- )));
+ self.switch_to_error_page(
+ &gettext!("Failed to restore previous sessions: {}", error),
+ error,
+ );
}
}
}
@@ -262,6 +270,12 @@ impl Window {
priv_.main_stack.set_visible_child(&*priv_.greeter);
}
+ pub fn switch_to_error_page(&self, message: &str, error: SecretError) {
+ let priv_ = self.imp();
+ priv_.error_page.display_secret_error(message, error);
+ priv_.main_stack.set_visible_child(&*priv_.error_page);
+ }
+
/// This appends a new toast to the list
pub fn add_toast(&self, toast: &Toast) {
self.imp().error_list.append(toast);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]