swift
dblogincomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QLabel>
7 #include <QLineEdit>
8 #include <QPlainTextEdit>
9 #include <QPushButton>
10 #include <QString>
11 #include <QWidget>
12 #include <Qt>
13 #include <QtGlobal>
14 
15 #include "ui_dblogincomponent.h"
16 
17 #include "config/buildconfig.h"
18 #include "core/data/globalsetup.h"
19 #include "gui/guiapplication.h"
20 #include "gui/guiutility.h"
22 #include "misc/crashhandler.h"
23 #include "misc/htmlutils.h"
24 #include "misc/logmessage.h"
26 #include "misc/network/url.h"
27 #include "misc/statusmessage.h"
28 #include "misc/verify.h"
29 
30 using namespace swift::core;
31 using namespace swift::core::db;
32 using namespace swift::gui;
33 using namespace swift::config;
34 using namespace swift::misc;
35 using namespace swift::misc::network;
36 
37 namespace swift::gui::components
38 {
39  CDbLoginComponent::CDbLoginComponent(QWidget *parent)
40  : QFrame(parent), CLoadIndicatorEnabled(this), ui(new Ui::CDbLoginComponent)
41  {
42  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Missing sGui");
43  ui->setupUi(this);
44  this->setModeLogin(true);
45  const QString urlString = asHyperlink(sGui->getGlobalSetup().getDbHomePageUrl().getFullUrl());
46  QString html = ui->tbr_InfoAndHints->toHtml();
47  html = html.replace("##swiftDB##", urlString, Qt::CaseInsensitive);
48  html = html.replace("##swiftEnableSSO##", urlString, Qt::CaseInsensitive);
49 
50  ui->tbr_InfoAndHints->setHtml(html);
51  ui->tbr_InfoAndHints->setOpenExternalLinks(true);
52 
53  const QString dbUrl = sGui->getGlobalSetup().getDbHomePageUrl().toQString();
54  ui->lbl_DatabaseName->setText(asHyperlink(dbUrl));
55  ui->lbl_DatabaseName->setTextFormat(Qt::RichText);
56  ui->lbl_DatabaseName->setTextInteractionFlags(Qt::TextBrowserInteraction);
57  ui->lbl_DatabaseName->setOpenExternalLinks(true);
58 
59  connect(ui->pb_Login, &QPushButton::clicked, this, &CDbLoginComponent::onLoginClicked);
60  connect(ui->pb_Logoff, &QPushButton::clicked, this, &CDbLoginComponent::onLogoffClicked);
61  connect(ui->le_Password, &QLineEdit::returnPressed, this, &CDbLoginComponent::onLoginClicked);
62  connect(&m_loginService, &CDatabaseAuthenticationService::userAuthenticationFinished, this,
63  &CDbLoginComponent::onAuthenticationFinished, Qt::QueuedConnection);
64 
65  if (CBuildConfig::isLocalDeveloperDebugBuild())
66  {
67  const QString url = sApp->getGlobalSetup().getDbLoginServiceUrl().toQString();
68  ui->pb_Login->setToolTip(url);
69  }
70 
71  // init GUI
72  this->setUserInfo(this->getDbUser());
73  }
74 
76 
77  CAuthenticatedUser CDbLoginComponent::getDbUser() const { return m_loginService.getDbUser(); }
78 
79  bool CDbLoginComponent::isUserAuthenticated() const { return m_loginService.isUserAuthenticated(); }
80 
81  void CDbLoginComponent::displayOverlayMessages(const CStatusMessageList &msgs)
82  {
83  if (msgs.isEmpty()) { return; }
85  SWIFT_VERIFY_X(mf, Q_FUNC_INFO, "No overlay widget");
86  if (!mf) { return; }
87  mf->showOverlayMessages(msgs);
88  }
89 
90  void CDbLoginComponent::onLoginClicked()
91  {
92  using namespace std::chrono_literals;
93  const QString un(ui->le_Username->text().trimmed());
94  const QString pw(ui->le_Password->text().trimmed());
95  const CStatusMessageList msgs = m_loginService.login(un, pw);
96 
97  if (msgs.hasWarningOrErrorMessages())
98  {
99  CLogMessage::preformatted(msgs);
100  displayOverlayMessages(msgs);
101  return;
102  }
103  else if (!msgs.isEmpty()) { CLogMessage::preformatted(msgs); }
104  this->showLoading(5s);
105  }
106 
107  void CDbLoginComponent::onLogoffClicked()
108  {
109  m_loginService.logoff();
110  this->setModeLogin(true);
111  }
112 
113  void CDbLoginComponent::onAuthenticationFinished(const CAuthenticatedUser &user,
114  const CStatusMessageList &statusMsgs)
115  {
116  this->hideLoading();
117  this->setUserInfo(user);
118  if (statusMsgs.hasWarningOrErrorMessages())
119  {
120  this->displayOverlayMessages(statusMsgs);
121  CLogMessage::preformatted(statusMsgs);
122  ui->le_Info->setText("Authentication failed, see hints");
123  }
124  }
125 
126  void CDbLoginComponent::setModeLogin(bool modeLogin) { ui->sw_LoginLogoff->setCurrentIndex(modeLogin ? 0 : 1); }
127 
128  void CDbLoginComponent::setUserInfo(const CAuthenticatedUser &user)
129  {
130  if (!sGui || sGui->isShuttingDown()) { return; }
131  if (user.isAuthenticated())
132  {
133  CLogMessage(this).info(u"User authenticated: %1") << user.toQString();
134  this->setModeLogin(false);
135  ui->le_Name->setText(user.getRealNameAndId());
136  ui->te_Roles->setPlainText(user.getRolesAsString());
137  if (user.canDirectlyWriteModels()) { ui->le_Info->setText("You can directly update models"); }
138  else { ui->le_Info->setText("You can create model change requests"); }
139 
140  // crashpad info
141  CCrashHandler::instance()->crashAndLogInfoUserName(user.getRealNameAndId());
142  CCrashHandler::instance()->crashAndLogAppendInfo(
143  QStringLiteral("Login as user %1 %2").arg(user.getRealNameAndId(), user.getRolesAsString()));
144  }
145  else
146  {
147  ui->le_Name->clear();
148  ui->te_Roles->clear();
149  this->setModeLogin(true);
150  }
151  }
152 } // namespace swift::gui::components
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
data::CGlobalSetup getGlobalSetup() const
Global setup.
bool isShuttingDown() const
Is application shutting down?
swift::misc::network::CUrl getDbHomePageUrl() const
Home page url.
Definition: globalsetup.cpp:42
swift::misc::network::CUrl getDbLoginServiceUrl() const
Login service.
Definition: globalsetup.cpp:61
swift::misc::network::CAuthenticatedUser getDbUser() const
DB user.
static COverlayMessagesFrame * nextOverlayMessageFrame(QWidget *widget, int maxLevels=10)
Find next COverlayMessagesFrame.
Definition: guiutility.cpp:435
Enable widget class for load indicator.
void showLoading(std::chrono::milliseconds timeout=std::chrono::milliseconds(0), bool processEvents=true)
Show load indicator.
void hideLoading()
Hide load indicator.
void showOverlayMessages(const swift::misc::CStatusMessageList &messages, bool appendOldMessages=false, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show multiple messages.
Using this class provides a QFrame with the overlay functionality already integrated.
bool isUserAuthenticated() const
Is user authenticated?
swift::misc::network::CAuthenticatedUser getDbUser() const
DB user.
Class for emitting a log message.
Definition: logmessage.h:27
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Status messages, e.g. from Core -> GUI.
bool hasWarningOrErrorMessages() const
Warning or error messages.
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
Value object encapsulating information of an authentiated user.
bool isAuthenticated() const
Authenticated.
bool canDirectlyWriteModels() const
Entitled to directly update models.
QString getRealNameAndId() const
Full name + id.
QString getFullUrl(bool withQuery=true) const
Qualified name.
Definition: url.cpp:84
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Classes interacting with the swift database (aka "datastore").
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
GUI related classes.
Free functions in swift::misc.
QString asHyperlink(const QString &url, const QString &text)
As hyperlink.
Definition: htmlutils.cpp:31
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26