From a6b69401438c9949486d961d94357c41977cccfe Mon Sep 17 00:00:00 2001
From: meizhigang <meizhigang@kylinsec.com.cn>
Date: Tue, 15 Aug 2023 20:52:36 +0800
Subject: [PATCH] fix(accounts):Fix user icon file display while change and
 login
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

 - 适配在更改用户图标后切换登录

 Related #12711
---
 plugins/accounts/user.cpp | 81 +++++++++++++++++++++++++++++++++++----
 plugins/accounts/user.h   |  7 +++-
 2 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/plugins/accounts/user.cpp b/plugins/accounts/user.cpp
index b0ad852..6c9864b 100644
--- a/plugins/accounts/user.cpp
+++ b/plugins/accounts/user.cpp
@@ -33,7 +33,12 @@ namespace Kiran
 {
 #define USERDIR "/var/lib/AccountsService/users"
 #define ICONDIR "/var/lib/AccountsService/icons"
-#define ACCOUNTS_USER_OBJECT_PATH "/com/kylinsec/Kiran/SystemDaemon/Accounts/User"
+#define KIRAN_ACCOUNTS_USER_OBJECT_PATH "/com/kylinsec/Kiran/SystemDaemon/Accounts/User"
+
+#define FREEDESKTOP_ACCOUNTS_DBUS_NAME "org.freedesktop.Accounts"
+#define FREEDESKTOP_ACCOUNTS_OBJECT_PATH "/org/freedesktop/Accounts"
+#define FREEDESKTOP_ACCOUNTS_DBUS_INTERFACE "org.freedesktop.Accounts"
+#define FREEDESKTOP_ACCOUNTS_USER_DBUS_INTERFACE "org.freedesktop.Accounts.User"
 
 User::User(PasswdShadow passwd_shadow) : passwd_shadow_(passwd_shadow),
                                          object_register_id_(0),
@@ -62,7 +67,7 @@ std::shared_ptr<User> User::create_user(PasswdShadow passwd_shadow)
 void User::dbus_register()
 {
     KLOG_PROFILE("Uid: %" PRIu64, this->uid_);
-    this->object_path_ = fmt::format(ACCOUNTS_USER_OBJECT_PATH "/{0}", this->uid_get());
+    this->object_path_ = fmt::format(KIRAN_ACCOUNTS_USER_OBJECT_PATH "/{0}", this->uid_get());
     try
     {
         this->dbus_connect_ = Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SYSTEM);
@@ -298,6 +303,7 @@ void User::GetAuthItems(gint32 mode, MethodInvocation &invocation)
 
 void User::init()
 {
+    this->build_freedesktop_user_object_path();
     this->udpate_nocache_var(this->passwd_shadow_);
     this->user_cache_ = std::make_shared<UserCache>(this->shared_from_this());
     // 由于图标路径是维护在缓存中，所以必须等UserCache对象创建后才能操作
@@ -631,6 +637,7 @@ void User::change_icon_file_authorized_cb(MethodInvocation invocation, const Gli
     } while (0);
 
     this->icon_file_set(filename);
+    this->sync_icon_file_to_freedesktop(filename);
     invocation.ret();
 }
 
@@ -974,12 +981,6 @@ USER_PROP_SET_HANDLER(automatic_login, bool);
 USER_PROP_SET_HANDLER(system_account, bool);
 USER_PROP_SET_HANDLER(password_expiration_policy, const Glib::ustring &);
 
-bool User::icon_file_changed(const Glib::ustring &value)
-{
-    this->icon_file_set(value);
-    return false;
-}
-
 AccountsAccountType User::account_type_from_pwent(std::shared_ptr<Passwd> passwd)
 {
     g_return_val_if_fail(passwd, AccountsAccountType::ACCOUNTS_ACCOUNT_TYPE_STANDARD);
@@ -1023,6 +1024,7 @@ void User::reset_icon_file()
         if (icon_file != this->default_icon_file_)
         {
             this->icon_file_set(this->default_icon_file_);
+            this->sync_icon_file_to_freedesktop(this->default_icon_file_);
         }
     }
 }
@@ -1034,4 +1036,67 @@ void User::move_extra_data(const std::string &old_name, const std::string &new_n
     g_rename(old_filename.c_str(), new_filename.c_str());
 }
 
+void User::build_freedesktop_user_object_path()
+{
+    this->freedesktop_object_path_ = Glib::DBusObjectPathString();
+
+    Glib::RefPtr<Gio::DBus::Proxy> account_proxy;
+    try
+    {
+        account_proxy = Gio::DBus::Proxy::create_for_bus_sync(Gio::DBus::BUS_TYPE_SYSTEM,
+                                                              FREEDESKTOP_ACCOUNTS_DBUS_NAME,
+                                                              FREEDESKTOP_ACCOUNTS_OBJECT_PATH,
+                                                              FREEDESKTOP_ACCOUNTS_DBUS_INTERFACE);
+    }
+    catch (const Glib::Error &e)
+    {
+        KLOG_WARNING("%s", e.what().c_str());
+        return;
+    }
+
+    auto parameters = g_variant_new("(x)", this->uid_get());
+    Glib::VariantContainerBase base(parameters, false);
+    try
+    {
+        auto retval = account_proxy->call_sync("FindUserById", base);
+        auto v1 = retval.get_child(0);
+        this->freedesktop_object_path_ = Glib::VariantBase::cast_dynamic<Glib::Variant<Glib::DBusObjectPathString>>(v1).get().raw();
+    }
+    catch (const Glib::Error &e)
+    {
+        KLOG_WARNING("%s", e.what().c_str());
+    }
+}
+
+void User::sync_icon_file_to_freedesktop(const Glib::ustring &icon_file)
+{
+    RETURN_IF_TRUE(this->freedesktop_object_path_.empty());
+
+    Glib::RefPtr<Gio::DBus::Proxy> account_proxy;
+    try
+    {
+        account_proxy = Gio::DBus::Proxy::create_for_bus_sync(Gio::DBus::BUS_TYPE_SYSTEM,
+                                                              FREEDESKTOP_ACCOUNTS_DBUS_NAME,
+                                                              this->freedesktop_object_path_,
+                                                              FREEDESKTOP_ACCOUNTS_USER_DBUS_INTERFACE);
+    }
+    catch (const Glib::Error &e)
+    {
+        KLOG_WARNING("%s", e.what().c_str());
+        return;
+    }
+
+    auto parameters = g_variant_new("(s)", icon_file.c_str());
+    Glib::VariantContainerBase base(parameters, false);
+    Glib::VariantContainerBase retval;
+    try
+    {
+        retval = account_proxy->call_sync("SetIconFile", base);
+    }
+    catch (const Glib::Error &e)
+    {
+        KLOG_WARNING("%s", e.what().c_str());
+    }
+}
+
 }  // namespace Kiran
\ No newline at end of file
diff --git a/plugins/accounts/user.h b/plugins/accounts/user.h
index f467cd5..5915504 100644
--- a/plugins/accounts/user.h
+++ b/plugins/accounts/user.h
@@ -208,12 +208,16 @@ private:
     // 模式转为对应的keyfile的group_name
     std::string mode_to_groupname(int32_t mode);
 
-    bool icon_file_changed(const Glib::ustring &value);
     AccountsAccountType account_type_from_pwent(std::shared_ptr<Passwd> passwd);
     void reset_icon_file();
 
     void move_extra_data(const std::string &old_name, const std::string &new_name);
 
+    void build_freedesktop_user_object_path();
+
+    // 由于切换用户时，登陆器通过org.freedesktop.Accounts接口获取图标，Kiran设置/更新用户图标后需要同步到freedesktop
+    void sync_icon_file_to_freedesktop(const Glib::ustring &icon_file);
+
 private:
 private:
     Glib::RefPtr<Gio::DBus::Connection> dbus_connect_;
@@ -224,6 +228,7 @@ private:
     uint32_t object_register_id_;
 
     Glib::DBusObjectPathString object_path_;
+    Glib::DBusObjectPathString freedesktop_object_path_;
 
     std::string default_icon_file_;
     std::shared_ptr<Passwd> passwd_;
-- 
2.27.0

