Files
Adaptix-Framework-AdaptixC2/AdaptixClient/Source/UI/Widgets/CredentialsWidget.cpp
T
2025-07-09 09:23:25 +03:00

473 lines
17 KiB
C++

#include <UI/Widgets/CredentialsWidget.h>
#include <UI/Widgets/AdaptixWidget.h>
#include <UI/Dialogs/DialogCredential.h>
#include <Client/Requestor.h>
#include <Client/AuthProfile.h>
#include <Utils/CustomElements.h>
CredentialsWidget::CredentialsWidget(AdaptixWidget* w) : adaptixWidget(w)
{
this->createUI();
connect(tableWidget, &QTableWidget::customContextMenuRequested, this, &CredentialsWidget::handleCredentialsMenu);
connect(tableWidget, &QTableWidget::cellDoubleClicked, this, &CredentialsWidget::onEditCreds);
connect(tableWidget, &QTableWidget::itemSelectionChanged, this, [this](){tableWidget->setFocus();} );
connect(hideButton, &ClickableLabel::clicked, this, &CredentialsWidget::toggleSearchPanel);
connect(inputFilter, &QLineEdit::textChanged, this, &CredentialsWidget::onFilterUpdate);
shortcutSearch = new QShortcut(QKeySequence("Ctrl+F"), tableWidget);
shortcutSearch->setContext(Qt::WidgetShortcut);
connect(shortcutSearch, &QShortcut::activated, this, &CredentialsWidget::toggleSearchPanel);
}
CredentialsWidget::~CredentialsWidget() = default;
void CredentialsWidget::createUI()
{
auto horizontalSpacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
searchWidget = new QWidget(this);
searchWidget->setVisible(false);
inputFilter = new QLineEdit(searchWidget);
inputFilter->setPlaceholderText("filter");
inputFilter->setMaximumWidth(300);
hideButton = new ClickableLabel("X");
hideButton->setCursor( Qt::PointingHandCursor );
searchLayout = new QHBoxLayout(searchWidget);
searchLayout->setContentsMargins(0, 5, 0, 0);
searchLayout->setSpacing(4);
searchLayout->addWidget(inputFilter);
searchLayout->addWidget(hideButton);
searchLayout->addSpacerItem(horizontalSpacer2);
tableWidget = new QTableWidget( this );
tableWidget->setColumnCount( 10 );
tableWidget->setContextMenuPolicy( Qt::CustomContextMenu );
tableWidget->setAutoFillBackground( false );
tableWidget->setShowGrid( false );
tableWidget->setSortingEnabled( true );
tableWidget->setWordWrap( true );
tableWidget->setCornerButtonEnabled( false );
tableWidget->setSelectionBehavior( QAbstractItemView::SelectRows );
tableWidget->setFocusPolicy( Qt::NoFocus );
tableWidget->setAlternatingRowColors( true );
tableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
tableWidget->horizontalHeader()->setCascadingSectionResizes( true );
tableWidget->horizontalHeader()->setHighlightSections( false );
tableWidget->verticalHeader()->setVisible( false );
tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("CredId"));
tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Username"));
tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Password"));
tableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("Realm"));
tableWidget->setHorizontalHeaderItem(4, new QTableWidgetItem("Type"));
tableWidget->setHorizontalHeaderItem(5, new QTableWidgetItem("Tag"));
tableWidget->setHorizontalHeaderItem(6, new QTableWidgetItem("Date"));
tableWidget->setHorizontalHeaderItem(7, new QTableWidgetItem("Storage"));
tableWidget->setHorizontalHeaderItem(8, new QTableWidgetItem("Agent"));
tableWidget->setHorizontalHeaderItem(9, new QTableWidgetItem("Host"));
tableWidget->hideColumn(0);
mainGridLayout = new QGridLayout( this );
mainGridLayout->setContentsMargins( 0, 0, 0, 0);
mainGridLayout->addWidget( searchWidget, 0, 0, 1, 1);
mainGridLayout->addWidget( tableWidget, 1, 0, 1, 1);
}
bool CredentialsWidget::filterItem(const CredentialData &credentials) const
{
if ( !this->searchWidget->isVisible() )
return true;
QString filter1 = this->inputFilter->text();
if( !filter1.isEmpty() ) {
if ( credentials.Username.contains(filter1, Qt::CaseInsensitive) ||
credentials.Password.contains(filter1, Qt::CaseInsensitive) ||
credentials.Realm.contains(filter1, Qt::CaseInsensitive) ||
credentials.Type.contains(filter1, Qt::CaseInsensitive) ||
credentials.Tag.contains(filter1, Qt::CaseInsensitive) ||
credentials.Storage.contains(filter1, Qt::CaseInsensitive) ||
credentials.Host.contains(filter1, Qt::CaseInsensitive) ||
credentials.AgentId.contains(filter1, Qt::CaseInsensitive)
)
return true;
else
return false;
}
return true;
}
void CredentialsWidget::addTableItem(const CredentialData &newCredentials) const
{
auto item_CredId = new QTableWidgetItem( newCredentials.CredId );
auto item_Username = new QTableWidgetItem( newCredentials.Username );
auto item_Password = new QTableWidgetItem( newCredentials.Password );
auto item_Realm = new QTableWidgetItem( newCredentials.Realm );
auto item_Type = new QTableWidgetItem( newCredentials.Type );
auto item_Tag = new QTableWidgetItem( newCredentials.Tag );
auto item_Date = new QTableWidgetItem( newCredentials.Date );
auto item_Storage = new QTableWidgetItem( newCredentials.Storage );
auto item_Agent = new QTableWidgetItem( newCredentials.AgentId );
auto item_Host = new QTableWidgetItem( newCredentials.Host );
item_Username->setFlags( item_Username->flags() ^ Qt::ItemIsEditable );
item_Username->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
item_Password->setFlags( item_Password->flags() ^ Qt::ItemIsEditable );
item_Password->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
item_Realm->setFlags( item_Realm->flags() ^ Qt::ItemIsEditable );
item_Realm->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
item_Type->setFlags( item_Type->flags() ^ Qt::ItemIsEditable );
item_Type->setTextAlignment( Qt::AlignCenter );
item_Tag->setFlags( item_Tag->flags() ^ Qt::ItemIsEditable );
item_Tag->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
item_Date->setFlags( item_Date->flags() ^ Qt::ItemIsEditable );
item_Date->setTextAlignment( Qt::AlignCenter );
item_Storage->setFlags( item_Storage->flags() ^ Qt::ItemIsEditable );
item_Storage->setTextAlignment( Qt::AlignCenter );
item_Agent->setFlags( item_Agent->flags() ^ Qt::ItemIsEditable );
item_Agent->setTextAlignment( Qt::AlignCenter );
item_Host->setFlags( item_Host->flags() ^ Qt::ItemIsEditable );
item_Host->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
if( tableWidget->rowCount() < 1 )
tableWidget->setRowCount( 1 );
else
tableWidget->setRowCount( tableWidget->rowCount() + 1 );
bool isSortingEnabled = tableWidget->isSortingEnabled();
tableWidget->setSortingEnabled( false );
tableWidget->setItem( tableWidget->rowCount() - 1, 0, item_CredId );
tableWidget->setItem( tableWidget->rowCount() - 1, 1, item_Username );
tableWidget->setItem( tableWidget->rowCount() - 1, 2, item_Password );
tableWidget->setItem( tableWidget->rowCount() - 1, 3, item_Realm );
tableWidget->setItem( tableWidget->rowCount() - 1, 4, item_Type );
tableWidget->setItem( tableWidget->rowCount() - 1, 5, item_Tag );
tableWidget->setItem( tableWidget->rowCount() - 1, 6, item_Date );
tableWidget->setItem( tableWidget->rowCount() - 1, 7, item_Storage );
tableWidget->setItem( tableWidget->rowCount() - 1, 8, item_Agent );
tableWidget->setItem( tableWidget->rowCount() - 1, 9, item_Host );
tableWidget->setSortingEnabled( isSortingEnabled );
tableWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::ResizeToContents );
tableWidget->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::ResizeToContents );
tableWidget->horizontalHeader()->setSectionResizeMode( 3, QHeaderView::ResizeToContents );
tableWidget->horizontalHeader()->setSectionResizeMode( 6, QHeaderView::ResizeToContents );
tableWidget->horizontalHeader()->setSectionResizeMode( 8, QHeaderView::ResizeToContents );
tableWidget->horizontalHeader()->setSectionResizeMode( 9, QHeaderView::ResizeToContents );
tableWidget->verticalHeader()->setSectionResizeMode(tableWidget->rowCount() - 1, QHeaderView::ResizeToContents);
}
/// Main
void CredentialsWidget::Clear() const
{
adaptixWidget->Credentials.clear();
this->ClearTableContent();
inputFilter->clear();
}
void CredentialsWidget::AddCredentialsItem(const CredentialData &newCredentials) const
{
for( auto creds : adaptixWidget->Credentials ) {
if( creds.CredId == newCredentials.CredId )
return;
}
adaptixWidget->Credentials.push_back(newCredentials);
if( !this->filterItem(newCredentials) )
return;
this->addTableItem(newCredentials);
}
void CredentialsWidget::EditCredentialsItem(const CredentialData &newCredentials) const
{
for ( int i = 0; i < adaptixWidget->Credentials.size(); i++ ) {
if( adaptixWidget->Credentials[i].CredId == newCredentials.CredId ) {
adaptixWidget->Credentials[i].Username = newCredentials.Username;
adaptixWidget->Credentials[i].Password = newCredentials.Password;
adaptixWidget->Credentials[i].Realm = newCredentials.Realm;
adaptixWidget->Credentials[i].Type = newCredentials.Type;
adaptixWidget->Credentials[i].Tag = newCredentials.Tag;
adaptixWidget->Credentials[i].Storage = newCredentials.Storage;
adaptixWidget->Credentials[i].Host = newCredentials.Host;
break;
}
}
for (int row = 0; row < tableWidget->rowCount(); ++row) {
QTableWidgetItem *item = tableWidget->item(row, 0);
if ( item && item->text() == newCredentials.CredId ) {
tableWidget->item(row, 1)->setText(newCredentials.Username);
tableWidget->item(row, 2)->setText(newCredentials.Password);
tableWidget->item(row, 3)->setText(newCredentials.Realm);
tableWidget->item(row, 4)->setText(newCredentials.Type);
tableWidget->item(row, 5)->setText(newCredentials.Tag);
tableWidget->item(row, 7)->setText(newCredentials.Storage);
tableWidget->item(row, 9)->setText(newCredentials.Host);
}
}
}
void CredentialsWidget::RemoveCredentialsItem(const QString &credId) const
{
for ( int i = 0; i < adaptixWidget->Credentials.size(); i++ ) {
if( adaptixWidget->Credentials[i].CredId == credId ) {
adaptixWidget->Credentials.erase( adaptixWidget->Credentials.begin() + i );
break;
}
}
for (int row = 0; row < tableWidget->rowCount(); ++row) {
QTableWidgetItem *item = tableWidget->item(row, 0);
if ( item && item->text() == credId ) {
tableWidget->removeRow(row);
break;
}
}
}
void CredentialsWidget::SetData() const
{
this->ClearTableContent();
for (int i = 0; i < adaptixWidget->Credentials.size(); i++ ) {
if ( this->filterItem(adaptixWidget->Credentials[i]) )
this->addTableItem(adaptixWidget->Credentials[i]);
}
}
void CredentialsWidget::ClearTableContent() const
{
for (int row = tableWidget->rowCount() - 1; row >= 0; row--) {
for (int col = 0; col < tableWidget->columnCount(); ++col)
tableWidget->takeItem(row, col);
tableWidget->removeRow(row);
}
}
/// Sender
void CredentialsWidget::CredentialsAdd(const QString &username, const QString &password, const QString &realm, const QString &type, const QString &tag, const QString &storage, const QString &host)
{
QJsonObject dataJson;
dataJson["username"] = username;
dataJson["password"] = password;
dataJson["realm"] = realm;
dataJson["type"] = type;
dataJson["tag"] = tag;
dataJson["storage"] = storage;
dataJson["host"] = host;
QByteArray jsonData = QJsonDocument(dataJson).toJson();
QString message = "";
bool ok = false;
bool result = HttpReqCredentialsCreate(jsonData, *(adaptixWidget->GetProfile()), &message, &ok);
if( !result ) {
MessageError("Server is not responding");
return;
}
if (!ok) MessageError(message);
}
/// Slots
void CredentialsWidget::toggleSearchPanel() const
{
if (this->searchWidget->isVisible())
this->searchWidget->setVisible(false);
else
this->searchWidget->setVisible(true);
this->SetData();
}
void CredentialsWidget::onFilterUpdate() const { this->SetData(); }
void CredentialsWidget::handleCredentialsMenu(const QPoint &pos ) const
{
auto ctxMenu = QMenu();
ctxMenu.addAction("Create", this, &CredentialsWidget::onCreateCreds );
ctxMenu.addAction("Edit", this, &CredentialsWidget::onEditCreds );
ctxMenu.addAction("Remove", this, &CredentialsWidget::onRemoveCreds );
ctxMenu.addSeparator();
ctxMenu.addAction("Export", this, &CredentialsWidget::onExportCreds );
QPoint globalPos = tableWidget->mapToGlobal(pos);
ctxMenu.exec(globalPos);
}
void CredentialsWidget::onCreateCreds()
{
DialogCredential* dialogCreds = new DialogCredential();
while (true) {
dialogCreds->StartDialog();
if (dialogCreds->IsValid())
break;
QString msg = dialogCreds->GetMessage();
if (msg.isEmpty()) {
delete dialogCreds;
return;
}
MessageError(msg);
}
CredentialData credData = dialogCreds->GetCredData();
delete dialogCreds;
this->CredentialsAdd(credData.Username, credData.Password, credData.Realm, credData.Type, credData.Tag, credData.Storage, credData.Host);
}
void CredentialsWidget::onEditCreds() const
{
if (tableWidget->selectionModel()->selectedRows().empty())
return;
auto credId = tableWidget->item( tableWidget->currentRow(), 0 )->text();
bool found = false;
CredentialData credentialData;
for (auto creds : adaptixWidget->Credentials) {
if (creds.CredId == credId) {
credentialData = creds;
found = true;
break;
}
}
if (!found)
return;
DialogCredential* dialogCreds = new DialogCredential();
dialogCreds->SetEditmode(credentialData);
while (true) {
dialogCreds->StartDialog();
if (dialogCreds->IsValid())
break;
QString msg = dialogCreds->GetMessage();
if (msg.isEmpty()) {
delete dialogCreds;
return;
}
MessageError(msg);
}
CredentialData credData = dialogCreds->GetCredData();
QJsonObject dataJson;
dataJson["cred_id"] = credData.CredId;
dataJson["username"] = credData.Username;
dataJson["password"] = credData.Password;
dataJson["realm"] = credData.Realm;
dataJson["type"] = credData.Type;
dataJson["tag"] = credData.Tag;
dataJson["storage"] = credData.Storage;
dataJson["host"] = credData.Host;
QByteArray jsonData = QJsonDocument(dataJson).toJson();
delete dialogCreds;
QString message = "";
bool ok = false;
bool result = HttpReqCredentialsEdit(jsonData, *(adaptixWidget->GetProfile()), &message, &ok);
if( !result ) {
MessageError("Server is not responding");
delete dialogCreds;
return;
}
if (!ok) MessageError(message);
}
void CredentialsWidget::onRemoveCreds() const
{
if (tableWidget->selectionModel()->selectedRows().empty())
return;
auto credId = tableWidget->item( tableWidget->currentRow(), 0 )->text();
QString message = QString();
bool ok = false;
bool result = HttpReqCredentialsRemove(credId, *(adaptixWidget->GetProfile()), &message, &ok);
if( !result ){
MessageError("Response timeout");
return;
}
if ( !ok ) MessageError(message);
}
void CredentialsWidget::onExportCreds() const
{
if (tableWidget->selectionModel()->selectedRows().empty())
return;
QInputDialog dialog;
dialog.setWindowTitle("Format for saving");
dialog.setLabelText("Format:");
dialog.setTextValue("%realm%\\%username%:%password%");
QLineEdit *lineEdit = dialog.findChild<QLineEdit*>();
if (lineEdit) {
lineEdit->setMinimumWidth(400);
}
bool inputOk = (dialog.exec() == QDialog::Accepted);
if (!inputOk)
return;
QString format = dialog.textValue();
QString fileName = QFileDialog::getSaveFileName( nullptr, "Save credentials", "creds.txt", "Text Files (*.txt);;All Files (*)" );
if ( fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
MessageError("Failed to open file for writing");
return;
}
QString content = "";
for( int rowIndex = 0 ; rowIndex < tableWidget->rowCount() ; rowIndex++ ) {
if ( tableWidget->item(rowIndex, 1)->isSelected() ) {
QString realm = tableWidget->item(rowIndex, 3)->text();
QString username = tableWidget->item(rowIndex, 1)->text();
QString password = tableWidget->item(rowIndex, 2)->text();
QString temp = format;
content += temp
.replace("%realm%", realm)
.replace("%username%", username)
.replace("%password%", password)
+ "\n";
}
}
file.write(content.trimmed().toUtf8());
file.close();
}