1 /*
2     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
3     SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
4 */
5 
6 #include "groupmanager.h"
7 
8 #include <QProcess>
9 #include <QFileInfo>
10 #include <QDebug>
11 
12 #include <KUser>
13 #include <KAuth/KAuthAction>
14 #include <KAuth/KAuthExecuteJob>
15 #include <KLocalizedString>
16 
GroupManager(QObject * parent)17 GroupManager::GroupManager(QObject *parent)
18     : QObject(parent)
19 {
20     metaObject()->invokeMethod(this, [this] {
21         auto proc = new QProcess;
22         proc->setProgram(QStringLiteral("testparm"));
23         proc->setArguments({QStringLiteral("--debuglevel=0"),
24                             QStringLiteral("--suppress-prompt"),
25                             QStringLiteral("--verbose"),
26                             QStringLiteral("--parameter-name"),
27                             QStringLiteral("usershare path")});
28         connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this, proc](int exitCode) {
29             proc->deleteLater();
30             const QString path = QString::fromUtf8(proc->readAllStandardOutput().simplified());
31 
32             m_ready = true;
33             Q_EMIT isReadyChanged();
34 
35             QFileInfo info(path);
36             if (exitCode != 0 || path.isEmpty() || !info.exists()) {
37                 return; // usershares may be disabled or path is invalid :|
38             }
39 
40             if (info.isWritable()) {
41                 m_isMember = true;
42                 Q_EMIT isMemberChanged();
43             }
44 
45             m_targetGroup = info.group();
46             Q_EMIT targetGroupChanged();
47 
48             if (m_targetGroup != QLatin1String("root") && m_targetGroup.contains(QLatin1String("samba"))) {
49                 m_canMakeMember = true;
50                 Q_EMIT canMakeMemberChanged();
51             }
52         });
53         proc->start();
54     });
55 }
56 
canMakeMember() const57 bool GroupManager::canMakeMember() const
58 {
59     return m_canMakeMember;
60 }
61 
isReady() const62 bool GroupManager::isReady() const
63 {
64     return m_ready;
65 }
66 
targetGroup() const67 QString GroupManager::targetGroup() const
68 {
69     return m_targetGroup;
70 }
71 
isMember() const72 bool GroupManager::isMember() const
73 {
74     return m_isMember;
75 }
76 
makeMember()77 void GroupManager::makeMember()
78 {
79     Q_ASSERT(m_canMakeMember);
80     const QString user = KUser().loginName();
81     const QString group = m_targetGroup;
82     Q_ASSERT(!user.isEmpty());
83     Q_ASSERT(!group.isEmpty());
84     auto action = KAuth::Action(QStringLiteral("org.kde.filesharing.samba.addtogroup"));
85     action.setHelperId(QStringLiteral("org.kde.filesharing.samba"));
86     action.addArgument(QStringLiteral("user"), user);
87     action.addArgument(QStringLiteral("group"), group);
88     action.setDetailsV2({{KAuth::Action::AuthDetail::DetailMessage,
89                           i18nc("@label kauth action description %1 is a username %2 a group name",
90                                 "Adding user '%1' to group '%2' so they may configure Samba user shares",
91                                 user,
92                                 group) }
93     });
94     KAuth::ExecuteJob *job = action.execute();
95     connect(job, &KAuth::ExecuteJob::result, this, [this, job] {
96         job->deleteLater();
97         if (job->error() != KAuth::ExecuteJob::NoError) {
98             Q_EMIT makeMemberError(job->errorString());
99             return;
100         }
101         Q_EMIT madeMember();
102     });
103     job->start();
104 }
105