Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
92299be
Utilize real default password settings
May 27, 2026
49ea381
Put default password settings in PSO containet widget
Jun 11, 2026
2062c86
Remove some unneeded vars
Jun 11, 2026
bc8abc5
Make default PSO readonly
Jun 12, 2026
9b4540a
Remove comented out code
Jun 12, 2026
5931022
Remove unused function
Jun 17, 2026
615469b
Move global password settings retrieval to utils
Jun 24, 2026
28fbb35
Rework PSOEditWidget update and get_settings to work with global pass…
Jun 24, 2026
67ad01d
Utilize new pso update logic
Jun 24, 2026
3c9ef8a
Refactor update defaults in PSOEditWidget
Jun 24, 2026
abc54f1
Add boolean attributes support in global password settings
Jun 24, 2026
7196f77
Move part of PSOEditWidget update function in a new one
Jun 24, 2026
5aee846
Remove update_default form PSOEditWidget
Jun 24, 2026
9dd5f16
Fix uneditable PSO name
Jun 25, 2026
cbbabf8
Fix zeroes in global PSO
Jun 30, 2026
280293d
Add some Doxygen coments
Jun 30, 2026
328bdb8
Remove unneeded code from console object impl
Jun 30, 2026
2c77e5a
Fix PSO container actions
Jul 1, 2026
9866ef8
chore: Format PasswordSettingsImpl
Jul 1, 2026
eae8fd6
style: Add title for global password settings
Jul 1, 2026
9f6482b
fix(PSO): Disable create pso action when pso container is unavailable
Jul 8, 2026
8d0dfd5
refactor: Remove some unneeded vars in password settings impl
Jul 13, 2026
22022a1
refactor: Make result widget and view protected in console impls
Jul 13, 2026
b05bf4d
fix: Fix refresh of pso console impl
Jul 13, 2026
97898f5
style: Remove extra var
Jul 13, 2026
8570daf
fix: Fix order of pso impl when pso container is not available
Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/adldap/ad_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ enum SystemFlagsBit {
#define ATTRIBUTE_MAX_PWD_AGE "maxPwdAge"
#define ATTRIBUTE_MIN_PWD_AGE "minPwdAge"
#define ATTRIBUTE_LOCKOUT_DURATION "lockoutDuration"
#define ATTRIBUTE_PWD_PROPERTIES "pwdProperties"
#define ATTRIBUTE_PWD_HISTORY_LENGTH "pwdHistoryLength"
#define ATTRIBUTE_MIN_PWD_LENGTH "minPwdLength"
#define ATTRIBUTE_LOCKOUT_THRESHOLD "lockoutThreshold"
#define ATTRIBUTE_IS_CRITICAL_SYSTEM_OBJECT "isCriticalSystemObject"
#define ATTRIBUTE_GPC_FILE_SYS_PATH "gPCFileSysPath"
#define ATTRIBUTE_GPC_FUNCTIONALITY_VERSION "gpCFunctionalityVersion"
Expand Down Expand Up @@ -407,6 +411,13 @@ const long long MILLIS_TO_100_NANOS = 10000LL;
#define ETYPES_AES128_CTS_HMAC_SHA1_96 0x00000008
#define ETYPES_AES256_CTS_HMAC_SHA1_96 0x00000010

#define SAM_MASK_DOMAIN_PASSWORD_COMPLEX 1
#define SAM_MASK_DOMAIN_PASSWORD_NO_ANON_CHANGE 2
#define SAM_MASK_DOMAIN_PASSWORD_NO_CLEAR_CHANGE 4
#define SAM_MASK_DOMAIN_LOCKOUT_ADMINS 8
#define SAM_MASK_DOMAIN_PASSWORD_STORE_CLEARTEXT 16
#define SAM_MASK_DOMAIN_REFUSE_PASSWORD_CHANGE 32

enum SearchScope {
SearchScope_Object,
SearchScope_Children,
Expand Down
1 change: 1 addition & 0 deletions src/admc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ set(ADMC_SOURCES
console_impls/policy_ou_impl.cpp
console_impls/found_policy_impl.cpp
console_impls/domain_info_impl.cpp
console_impls/password_settings_impl.cpp

permission_control_widgets/permissions_widget.cpp
permission_control_widgets/creation_deletion_permissions_widget.cpp
Expand Down
1 change: 1 addition & 0 deletions src/admc/console_impls/item_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum ItemType {
ItemType_FindPolicy,
ItemType_FoundPolicy,
ItemType_DomainInfo,
ItemType_PasswordSettings,

ItemType_LAST,
};
Expand Down
14 changes: 7 additions & 7 deletions src/admc/console_impls/object_impl/console_object_operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,17 +613,17 @@ bool ConsoleObjectTreeOperations::console_object_deletion_dialog(ConsoleWidget *
}

void ConsoleObjectTreeOperations::console_tree_add_password_settings(ConsoleWidget *console, AdInterface &ad) {
QStandardItem *password_settings_root = console->add_scope_item(ItemType_PasswordSettings, console->domain_info_index())[0];
password_settings_root->setText(QCoreApplication::translate("password_settings_impl", "Password settings"));
password_settings_root->setIcon(g_icon_manager->item_icon(ItemIcon_Password_Settings_Object));
password_settings_root->setDragEnabled(false);
const QString filter = filter_CONDITION(Condition_Equals, ATTRIBUTE_OBJECT_CLASS, CLASS_PSO_CONTAINER);
auto search_results = ad.search(g_adconfig->domain_dn(), SearchScope_All, filter, {});
const QString err = QObject::tr("Password settings container is not available");
if (search_results.isEmpty() || search_results.values()[0].is_empty()) {
g_status->add_message(err, StatusType_Info);
return;
if (!search_results.isEmpty() && !search_results.values()[0].is_empty()) {
console_object_item_data_load(password_settings_root, search_results.values()[0]);
}

const int pso_container_sort_idx = 3;
console_tree_add_root_child(console, search_results.values()[0], pso_container_sort_idx,
QObject::tr("Fine-grained password policies"));
console->set_item_sort_index(password_settings_root->index(), 3);
}

QString ConsoleObjectTreeOperations::console_object_count_string(ConsoleWidget *console, const QModelIndex &index) {
Expand Down
28 changes: 5 additions & 23 deletions src/admc/console_impls/object_impl/object_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,22 +212,11 @@ void ObjectImpl::activate(const QModelIndex &index) {
}

QList<QAction *> ObjectImpl::get_all_custom_actions() const {
QList<QAction *> out = {
new_action,
find_action,
add_to_group_action,
enable_action,
disable_action,
reset_password_action,
reset_account_action,
edit_upn_suffixes_action,
move_action,
create_pso_action,
create_subnet_action,
create_site_action,
create_site_link_action,
create_site_link_bridge_action
};
QList<QAction *> out = {new_action, find_action, add_to_group_action,
enable_action, disable_action, reset_password_action,
reset_account_action, edit_upn_suffixes_action, move_action,
create_subnet_action, create_site_action, create_site_link_action,
create_site_link_bridge_action};

return out;
}
Expand All @@ -247,7 +236,6 @@ QSet<QAction *> ObjectImpl::get_custom_actions(const QModelIndex &index, const b
const bool is_group = (object_class == CLASS_GROUP);
const bool is_domain = (object_class == CLASS_DOMAIN);
const bool is_computer = (object_class == CLASS_COMPUTER);
const bool is_pso_container = (object_class == CLASS_PSO_CONTAINER);
const bool is_sites_container = (object_class == CLASS_SITES_CONTAINER);
const bool is_subnet_container = (object_class == CLASS_SUBNET_CONTAINER);
const bool is_site_links_container = (object_class == CLASS_INTER_SITE_TRANSPORT);
Expand Down Expand Up @@ -285,10 +273,6 @@ QSet<QAction *> ObjectImpl::get_custom_actions(const QModelIndex &index, const b
out.insert(edit_upn_suffixes_action);
}

if (is_pso_container) {
out.insert(create_pso_action);
}

if (is_sites_container) {
out.insert(create_site_action);
}
Expand Down Expand Up @@ -1003,14 +987,12 @@ void ObjectImpl::setup_actions() {
new_menu->addAction(action);
}

create_pso_action = new QAction(tr("Create password setting object"), this);
create_subnet_action = new QAction(tr("Create subnet"), this);
create_site_action = new QAction(tr("Create site"), this);
create_site_link_action = new QAction(tr("Create site link"), this);
create_site_link_bridge_action = new QAction(tr("Create site link bridge"), this);

QHash<QString, QAction *> all_create_action_map {standard_create_action_map};
all_create_action_map[CLASS_PSO] = create_pso_action;
all_create_action_map[CLASS_SUBNET] = create_subnet_action;
all_create_action_map[CLASS_SITE] = create_site_action;
all_create_action_map[CLASS_SITE_LINK] = create_site_link_action;
Expand Down
1 change: 0 additions & 1 deletion src/admc/console_impls/object_impl/object_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ private slots:
QAction *reset_account_action;
QAction *edit_upn_suffixes_action;
QAction *new_action;
QAction *create_pso_action;
QAction *create_subnet_action;
QAction *create_site_action;
QAction *create_site_link_action;
Expand Down
127 changes: 127 additions & 0 deletions src/admc/console_impls/password_settings_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* ADMC - AD Management Center
*
* Copyright (C) 2020-2025 BaseALT Ltd.
* Copyright (C) 2020-2025 Dmitry Degtyarev

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to put here another line with copyright date and your name, if you are one of the authors of the file.

*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "console_impls/password_settings_impl.h"

#include "ad_defines.h"
#include "adldap.h"
#include "console_impls/item_type.h"
#include "console_impls/object_impl/object_impl.h"
#include "console_impls/policy_impl.h"
#include "console_widget/results_view.h"
#include "create_dialogs/create_policy_dialog.h"
#include "fsmo/fsmo_utils.h"
#include "globals.h"
#include "object_impl/console_object_operations.h"
#include "results_widgets/pso_results_widget/pso_results_widget.h"
#include "status.h"
#include "utils.h"

#include <QAction>
#include <QList>
#include <QMessageBox>
#include <QStandardItem>

PasswordSettingsImpl::PasswordSettingsImpl(ConsoleWidget *console_arg)
: ConsoleImpl(console_arg) {
results_widget = new PSOResultsWidget(console_arg);

create_pso_action =
new QAction(tr("Create password settings object"), this);

connect(create_pso_action, &QAction::triggered, this, [this]() {
const QString parent_dn = get_selected_target_dn(
console, ItemType_PasswordSettings, ObjectRole_DN);
ConsoleObjectTreeOperations::console_object_create(
{console}, CLASS_PSO, parent_dn);
});
}

void PasswordSettingsImpl::fetch(const QModelIndex &index) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put a Doxygen comment before methods, to document what the method does, what it accepts as parameters, what it asserts (if it does so) and what it returns. Also, if there are any exceptions that can be thrown in the method, I'd document them too.

AdInterface ad;
if (ad_failed(ad, console)) {
return;
}

//TODO:(kozyrevid) refactor this cast and other like it
dynamic_cast<PSOResultsWidget *>(results_widget)
->update(global_password_settings());

QHash<QString, AdObject> results = ad.search(
g_adconfig->pso_container_dn(), SearchScope_All, "", QStringList());
is_PSO_container_available = !results.isEmpty();
results.removeIf([](QHash<QString, AdObject>::iterator object) {
return object.value().get_string(ATTRIBUTE_OBJECT_CLASS) ==
CLASS_PSO_CONTAINER;
});

ConsoleObjectTreeOperations::add_objects_to_console(
console, results.values(), index);
}

void PasswordSettingsImpl::refresh(const QList<QModelIndex> &index_list) {
const QModelIndex index = index_list[0];

console->delete_children(index);
fetch(index);
}

QList<QAction *> PasswordSettingsImpl::get_all_custom_actions() const {
return {create_pso_action};
}

QSet<QAction *> PasswordSettingsImpl::get_custom_actions(
const QModelIndex &index, const bool single_selection) const {
UNUSED_ARG(index);
UNUSED_ARG(single_selection);

auto all_actions = get_all_custom_actions();
return {all_actions.begin(), all_actions.end()};
}

QSet<QAction *> PasswordSettingsImpl::get_disabled_custom_actions(
const QModelIndex &index, const bool single_selection) const {
UNUSED_ARG(index);
UNUSED_ARG(single_selection);

return is_PSO_container_available ? QSet<QAction *>{} :
QSet<QAction *>{create_pso_action};
}

QSet<StandardAction> PasswordSettingsImpl::get_standard_actions(
const QModelIndex &index, const bool single_selection) const {
UNUSED_ARG(index);
UNUSED_ARG(single_selection);

return {StandardAction_Refresh, StandardAction_Properties};
}

QList<QString> PasswordSettingsImpl::column_labels() const {
return ConsoleObjectTreeOperations::object_impl_column_labels();
}

QList<int> PasswordSettingsImpl::default_columns() const {
return ConsoleObjectTreeOperations::object_impl_default_columns();
}

void PasswordSettingsImpl::properties(const QList<QModelIndex> &index_list) {
ConsoleObjectTreeOperations::console_object_properties(
{console}, index_list, ObjectRole_DN, {CLASS_PSO_CONTAINER});
}
61 changes: 61 additions & 0 deletions src/admc/console_impls/password_settings_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* ADMC - AD Management Center
*
* Copyright (C) 2020-2025 BaseALT Ltd.
* Copyright (C) 2020-2025 Dmitry Degtyarev

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same comment about the copyright header here.

*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PASSWORD_SETTINGS_IMPL_H
#define PASSWORD_SETTINGS_IMPL_H

/**
* Impl for a virtual container for "All policies". Displays
* all of the policies present in the domain.
*/

#include "console_widget/console_impl.h"
#include "console_widget/console_widget.h"

class AdObject;
class AdInterface;

class PasswordSettingsImpl final : public ConsoleImpl {
Q_OBJECT

public:
PasswordSettingsImpl(ConsoleWidget *console_arg);

void fetch(const QModelIndex &index) override;
void refresh(const QList<QModelIndex> &index_list) override;
void properties(const QList<QModelIndex> &index_list) override;

QList<QAction *> get_all_custom_actions() const override;
QSet<QAction *> get_custom_actions(
const QModelIndex &index, const bool single_selection) const override;
QSet<QAction *> get_disabled_custom_actions(
const QModelIndex &index, const bool single_selection) const override;
QSet<StandardAction> get_standard_actions(
const QModelIndex &index, const bool single_selection) const override;

QList<QString> column_labels() const override;
QList<int> default_columns() const override;

private:
QAction *create_pso_action;
bool is_PSO_container_available = false;
};

#endif /* PASSWORD_SETTINGS_IMPL_H */
1 change: 0 additions & 1 deletion src/admc/console_widget/console_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ class ConsoleImpl : public QObject {
void set_results_view(ResultsView *view);
void set_results_widget(QWidget *widget);

private:
ResultsView *results_view;
QWidget *results_widget;
};
Expand Down
4 changes: 4 additions & 0 deletions src/admc/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include "main_window.h"
#include "console_impls/password_settings_impl.h"
#include "ui_main_window.h"

#include "about_dialog.h"
Expand Down Expand Up @@ -483,6 +484,9 @@ void MainWindow::init_on_connect(AdInterface &ad) {
auto policy_impl = new PolicyImpl(ui->console);
ui->console->register_impl(ItemType_Policy, policy_impl);

auto pso_impl = new PasswordSettingsImpl(ui->console);
ui->console->register_impl(ItemType_PasswordSettings, pso_impl);

auto query_item_impl = new QueryItemImpl(ui->console);
ui->console->register_impl(ItemType_QueryItem, query_item_impl);

Expand Down
Loading