mirror of
https://github.com/altlinux/admc.git
synced 2025-02-10 05:57:24 +03:00
add rename dialog
custom extra attribute edits for users and groups remove rename_user/group from adldap print untranslated/unreworded ldap error by default
This commit is contained in:
parent
8af5db2ace
commit
4e2f7c8687
@ -72,6 +72,7 @@ set(ADMC_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/general_tab.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/address_tab.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/object_tab.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/rename_dialog.cpp
|
||||
)
|
||||
|
||||
set(TS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/translations)
|
||||
|
@ -780,90 +780,6 @@ int ad_rename(LDAP *ld, const char *dn, const char *new_rdn) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int ad_rename_user(LDAP *ld, const char *dn, const char *new_name) {
|
||||
int result = AD_SUCCESS;
|
||||
|
||||
char* new_rdn = NULL;
|
||||
char* domain = NULL;
|
||||
char* upn = NULL;
|
||||
|
||||
const int result_replace_name = ad_attribute_replace(ld, dn, "sAMAccountName", new_name);
|
||||
if (result_replace_name != AD_SUCCESS) {
|
||||
// Failed to change sAMAccountName
|
||||
result = result_replace_name;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Construct userPrincipalName
|
||||
const int result_dn2domain = dn2domain(dn, &domain);
|
||||
if (result_dn2domain != AD_SUCCESS) {
|
||||
result = result_dn2domain;
|
||||
|
||||
goto end;
|
||||
}
|
||||
upn = malloc(strlen(new_name) + strlen(domain) + 2);
|
||||
sprintf(upn, "%s@%s", new_name, domain);
|
||||
|
||||
const int result_replace_upn = ad_attribute_replace(ld, dn, "userPrincipalName", upn);
|
||||
if (result_replace_upn != AD_SUCCESS) {
|
||||
// Failed to change userPrincipalName
|
||||
result = result_replace_upn;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
new_rdn = malloc(strlen(new_name) + 4);
|
||||
sprintf(new_rdn, "cn=%s", new_name);
|
||||
|
||||
const int result_rename = ad_rename(ld, dn, new_rdn);
|
||||
if (result_rename != AD_SUCCESS) {
|
||||
result = result_rename;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
{
|
||||
free(domain);
|
||||
free(upn);
|
||||
free(new_rdn);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
int ad_rename_group(LDAP *ld, const char *dn, const char *new_name) {
|
||||
int result = AD_SUCCESS;
|
||||
|
||||
char *new_rdn = NULL;
|
||||
|
||||
const int result_replace = ad_attribute_replace(ld, dn, "sAMAccountName", new_name);
|
||||
if (result_replace != AD_SUCCESS) {
|
||||
// Failed to change sAMAccountName
|
||||
result = result_replace;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
new_rdn = malloc(strlen(new_name) + 4);
|
||||
sprintf(new_rdn, "cn=%s", new_name);
|
||||
|
||||
const int result_rename = ldap_rename_s(ld, dn, new_rdn, NULL, 1, NULL, NULL);
|
||||
if (result_rename != LDAP_SUCCESS) {
|
||||
result = AD_LDAP_ERROR;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
{
|
||||
free(new_rdn);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
int ad_move_user(LDAP *ld, const char *current_dn, const char *new_container) {
|
||||
int result = AD_SUCCESS;
|
||||
|
||||
|
@ -116,14 +116,6 @@ int AdConnection::rename(const char *dn, const char *new_name) {
|
||||
return ad_rename(ldap_connection, dn, new_name);
|
||||
}
|
||||
|
||||
int AdConnection::rename_user(const char *dn, const char *new_username) {
|
||||
return ad_rename_user(ldap_connection, dn, new_username);
|
||||
}
|
||||
|
||||
int AdConnection::rename_group(const char *dn, const char *new_name) {
|
||||
return ad_rename_group(ldap_connection, dn, new_name);
|
||||
}
|
||||
|
||||
int AdConnection::move(const char *current_dn, const char *new_container) {
|
||||
return ad_move(ldap_connection, current_dn, new_container);
|
||||
}
|
||||
|
@ -175,23 +175,10 @@ int ad_attribute_delete(LDAP *ld, const char *dn, const char *attribute, const c
|
||||
|
||||
/**
|
||||
* Rename object
|
||||
* Use specialized functions to rename users and groups
|
||||
* Returns AD_SUCCESS, AD_LDAP_ERROR
|
||||
*/
|
||||
int ad_rename(LDAP *ld, const char *dn, const char *new_rdn);
|
||||
|
||||
/**
|
||||
* Rename user and update related attributes
|
||||
* Returns AD_SUCCESS, AD_LDAP_ERROR, AD_INVALID_DN
|
||||
*/
|
||||
int ad_rename_user(LDAP *ld, const char *dn, const char *new_name);
|
||||
|
||||
/**
|
||||
* Rename group and update related attributes
|
||||
* Returns AD_SUCCESS, AD_LDAP_ERROR
|
||||
*/
|
||||
int ad_rename_group(LDAP *ld, const char *dn, const char *new_name);
|
||||
|
||||
/**
|
||||
* Move object
|
||||
* Use ad_move_user() for user objects
|
||||
|
@ -51,8 +51,6 @@ public:
|
||||
int attribute_delete(const char *dn, const char *attribute, const char *value);
|
||||
int get_all_attributes(const char *dn, char ****attributes);
|
||||
int rename(const char *dn, const char *new_name);
|
||||
int rename_user(const char *dn, const char *new_username);
|
||||
int rename_group(const char *dn, const char *new_name);
|
||||
int move(const char *current_dn, const char *new_container);
|
||||
int move_user(const char *current_dn, const char *new_container);
|
||||
int create_group(const char *group_name, const char *dn);
|
||||
|
@ -521,19 +521,10 @@ AdResult AdInterface::object_rename(const QString &dn, const QString &new_name)
|
||||
|
||||
const QByteArray dn_array = dn.toLatin1();
|
||||
const char *dn_cstr = dn_array.constData();
|
||||
const QByteArray new_name_array = new_name.toLatin1();
|
||||
const char *new_name_cstr = new_name_array.constData();
|
||||
const QByteArray new_rdn_array = new_rdn.toLatin1();
|
||||
const char *new_rdn_cstr = new_rdn_array.constData();
|
||||
|
||||
int result = AD_ERROR;
|
||||
if (is_user(dn)) {
|
||||
result = connection->rename_user(dn_cstr, new_name_cstr);
|
||||
} else if (is_group(dn)) {
|
||||
result = connection->rename_group(dn_cstr, new_name_cstr);
|
||||
} else {
|
||||
result = connection->rename(dn_cstr, new_rdn_cstr);
|
||||
}
|
||||
int result = connection->rename(dn_cstr, new_rdn_cstr);
|
||||
|
||||
const QString old_name = extract_name_from_dn(dn);
|
||||
|
||||
@ -956,7 +947,11 @@ QString AdInterface::default_error_string(int ad_result) const {
|
||||
case LDAP_CONSTRAINT_VIOLATION: return tr("Constraint violation");
|
||||
case LDAP_UNWILLING_TO_PERFORM: return tr("Server is unwilling to perform");
|
||||
case LDAP_ALREADY_EXISTS: return tr("Already exists");
|
||||
default: return tr("Unknown LDAP error");
|
||||
default: {
|
||||
char *ldap_err = ldap_err2string(ldap_result);
|
||||
const QString ldap_err_qstr(ldap_err);
|
||||
return QString(tr("LDAP error: %1")).arg(ldap_err_qstr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (ad_result) {
|
||||
|
@ -37,15 +37,16 @@
|
||||
#define ISO8601_FORMAT_STRING "yyyyMMddhhmmss.zZ"
|
||||
|
||||
#define ATTRIBUTE_USER_ACCOUNT_CONTROL "userAccountControl"
|
||||
#define ATTRIBUTE_USER_PRINCIPAL_NAME "userPrincipalName"
|
||||
#define ATTRIBUTE_LOCKOUT_TIME "lockoutTime"
|
||||
#define ATTRIBUTE_ACCOUNT_EXPIRES "accountExpires"
|
||||
#define ATTRIBUTE_PWD_LAST_SET "pwdLastSet"
|
||||
#define ATTRIBUTE_NAME "name"
|
||||
#define ATTRIBUTE_INITIALS "initials"
|
||||
#define ATTRIBUTE_SAMACCOUNT_NAME "sAMAccountName"
|
||||
#define ATTRIBUTE_DISPLAY_NAME "displayName"
|
||||
#define ATTRIBUTE_DESCRIPTION "description"
|
||||
#define ATTRIBUTE_GIVEN_NAME "givenName"
|
||||
#define ATTRIBUTE_INITIALS "initials"
|
||||
#define ATTRIBUTE_USER_PRINCIPAL_NAME "userPrincipalName"
|
||||
#define ATTRIBUTE_MAIL "mail"
|
||||
#define ATTRIBUTE_OFFICE "physicalDeliveryOfficeName"
|
||||
#define ATTRIBUTE_SN "sn"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ad_interface.h"
|
||||
#include "confirmation_dialog.h"
|
||||
#include "move_dialog.h"
|
||||
#include "rename_dialog.h"
|
||||
#include "utils.h"
|
||||
#include "password_dialog.h"
|
||||
#include "settings.h"
|
||||
@ -82,7 +83,8 @@ void ObjectContextMenu::open(const QPoint &global_pos, const QString &dn, const
|
||||
delete_object(dn);
|
||||
});
|
||||
addAction(tr("Rename"), [this, dn]() {
|
||||
rename(dn);
|
||||
auto rename_dialog = new RenameDialog(dn, this);
|
||||
rename_dialog->open();
|
||||
});
|
||||
|
||||
QMenu *submenu_new = addMenu("New");
|
||||
@ -186,18 +188,6 @@ void ObjectContextMenu::new_object_dialog(const QString &parent_dn, NewObjectTyp
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectContextMenu::rename(const QString &dn) {
|
||||
// Get new name from input box
|
||||
QString dialog_title = tr("Rename");
|
||||
QString input_label = tr("New name:");
|
||||
bool ok;
|
||||
QString new_name = QInputDialog::getText(this, dialog_title, input_label, QLineEdit::Normal, "", &ok);
|
||||
|
||||
if (ok && !new_name.isEmpty()) {
|
||||
AdInterface::instance()->object_rename(dn, new_name);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectContextMenu::edit_policy(const QString &dn) {
|
||||
// Start policy edit process
|
||||
const auto process = new QProcess(this);
|
||||
|
@ -46,7 +46,6 @@ private:
|
||||
void open(const QPoint &global_pos, const QString &dn, const QString &parent_dn);
|
||||
void delete_object(const QString &dn);
|
||||
void new_object_dialog(const QString &parent_dn, NewObjectType type);
|
||||
void rename(const QString &dn);
|
||||
void edit_policy(const QString &dn);
|
||||
|
||||
};
|
||||
|
138
src/rename_dialog.cpp
Normal file
138
src/rename_dialog.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* ADMC - AD Management Center
|
||||
*
|
||||
* Copyright (C) 2020 BaseALT Ltd.
|
||||
*
|
||||
* 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 "rename_dialog.h"
|
||||
#include "ad_interface.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QList>
|
||||
|
||||
RenameDialog::RenameDialog(const QString &target_arg, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
target = target_arg;
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
resize(600, 600);
|
||||
|
||||
const QString name = AdInterface::instance()->attribute_get(target, ATTRIBUTE_NAME);
|
||||
const auto title_label = new QLabel(QString(tr("Renaming \"%1\":")).arg(name), this);
|
||||
|
||||
const auto ok_button = new QPushButton(tr("OK"), this);
|
||||
connect(
|
||||
ok_button, &QAbstractButton::clicked,
|
||||
this, &QDialog::accept);
|
||||
|
||||
const auto cancel_button = new QPushButton(tr("Cancel"), this);
|
||||
connect(
|
||||
cancel_button, &QAbstractButton::clicked,
|
||||
this, &QDialog::reject);
|
||||
|
||||
label_layout = new QVBoxLayout();
|
||||
edit_layout = new QVBoxLayout();
|
||||
|
||||
const auto attributes_layout = new QHBoxLayout();
|
||||
attributes_layout->insertLayout(-1, label_layout);
|
||||
attributes_layout->insertLayout(-1, edit_layout);
|
||||
|
||||
const auto top_layout = new QGridLayout(this);
|
||||
top_layout->addWidget(title_label, 0, 0);
|
||||
top_layout->addLayout(attributes_layout, 1, 0);
|
||||
top_layout->addWidget(cancel_button, 2, 0, Qt::AlignLeft);
|
||||
top_layout->addWidget(ok_button, 2, 2, Qt::AlignRight);
|
||||
|
||||
name_edit = {
|
||||
"",
|
||||
nullptr
|
||||
};
|
||||
|
||||
add_attribute_edit(ATTRIBUTE_NAME, tr("Name:"));
|
||||
|
||||
// Add extra name-related attribute edits for users/groups
|
||||
const bool is_user = AdInterface::instance()->is_user(target);
|
||||
const bool is_group = AdInterface::instance()->is_group(target);
|
||||
if (is_user) {
|
||||
add_attribute_edit(ATTRIBUTE_GIVEN_NAME, tr("First name:"));
|
||||
add_attribute_edit(ATTRIBUTE_SN, tr("Last name:"));
|
||||
add_attribute_edit(ATTRIBUTE_DISPLAY_NAME, tr("Display name:"));
|
||||
add_attribute_edit(ATTRIBUTE_USER_PRINCIPAL_NAME, tr("Logon name:"));
|
||||
add_attribute_edit(ATTRIBUTE_SAMACCOUNT_NAME, tr("Logon name (pre-2000):"));
|
||||
} if (is_group) {
|
||||
add_attribute_edit(ATTRIBUTE_SAMACCOUNT_NAME, tr("Logon name (pre-2000):"));
|
||||
}
|
||||
|
||||
connect(
|
||||
this, &QDialog::accepted,
|
||||
this, &RenameDialog::on_accepted);
|
||||
}
|
||||
|
||||
void RenameDialog::on_accepted() {
|
||||
auto push_changes_from_attribute_edit =
|
||||
[this](const AttributeEdit &e) {
|
||||
const QString attribute = e.attribute;
|
||||
const QLineEdit *edit = e.edit;
|
||||
|
||||
const QString current_value = AdInterface::instance()->attribute_get(target, attribute);
|
||||
const QString new_value = edit->text();
|
||||
|
||||
const bool changed = (new_value != current_value);
|
||||
if (changed) {
|
||||
if (attribute == ATTRIBUTE_NAME) {
|
||||
AdInterface::instance()->object_rename(target, new_value);
|
||||
} else {
|
||||
AdInterface::instance()->attribute_replace(target, attribute, new_value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: change name last so that other attribute changes can complete on old DN
|
||||
for (auto e : edits) {
|
||||
push_changes_from_attribute_edit(e);
|
||||
}
|
||||
|
||||
if (name_edit.edit != nullptr) {
|
||||
push_changes_from_attribute_edit(name_edit);
|
||||
}
|
||||
}
|
||||
|
||||
void RenameDialog::add_attribute_edit(const QString &attribute, const QString &label_text) {
|
||||
const auto label = new QLabel(label_text);
|
||||
auto edit = new QLineEdit();
|
||||
|
||||
label_layout->addWidget(label);
|
||||
edit_layout->addWidget(edit);
|
||||
|
||||
const QString current_value = AdInterface::instance()->attribute_get(target, attribute);
|
||||
edit->setText(current_value);
|
||||
|
||||
AttributeEdit attribute_edit = {
|
||||
QString(attribute),
|
||||
edit
|
||||
};
|
||||
|
||||
if (attribute == ATTRIBUTE_NAME) {
|
||||
name_edit = attribute_edit;
|
||||
} else {
|
||||
edits.append(attribute_edit);
|
||||
}
|
||||
}
|
54
src/rename_dialog.h
Normal file
54
src/rename_dialog.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ADMC - AD Management Center
|
||||
*
|
||||
* Copyright (C) 2020 BaseALT Ltd.
|
||||
*
|
||||
* 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 RENAME_DIALOG_H
|
||||
#define RENAME_DIALOG_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDialog>
|
||||
#include <QList>
|
||||
|
||||
class QLineEdit;
|
||||
class QVBoxLayout;
|
||||
|
||||
class RenameDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RenameDialog(const QString &target_arg, QWidget *parent);
|
||||
|
||||
private slots:
|
||||
void on_accepted();
|
||||
|
||||
private:
|
||||
struct AttributeEdit {
|
||||
QString attribute;
|
||||
QLineEdit *edit;
|
||||
};
|
||||
|
||||
QString target;
|
||||
QVBoxLayout *label_layout;
|
||||
QVBoxLayout *edit_layout;
|
||||
AttributeEdit name_edit;
|
||||
QList<AttributeEdit> edits;
|
||||
|
||||
void add_attribute_edit(const QString &attribute, const QString &label_text);
|
||||
};
|
||||
|
||||
#endif /* RENAME_DIALOG_H */
|
Loading…
x
Reference in New Issue
Block a user