Опубликован: 07.05.2010 | Уровень: специалист | Доступ: платный
Лекция 27:

Программное администрирование баз данных InterBase

< Лекция 26 || Лекция 27: 12345 || Лекция 28 >

Работа с пользователями

Определимся с задачей:

  1. Добавление нового пользователя.
  2. Изменение данных существующего пользователя (пароль, имя, отчество, фамилия). Если пользователь - SYSDBA, редактирование запрещаем. Ведь при резервном копировании и восстановлении мы жестко задавали имя SYSDBA и пароль masterkey (если вы изменили этот пароль, значит у вас свой вариант). И если администратор изменит этот пароль, программа не сможет работать, вам придется изменить этот пароль в программе и перекомпилировать ее. Впрочем, в дальнейшем вы можете усложнить программу, добавив в нее, например, работу с ini -файлом (см. "Ключи и индексы" курса "Введение в программирование на Delphi "). В этом случае, вы сможете прописать в ini -файл новый пароль пользователя SYSDBA, если администратор изменит его, и в дальнейшем использовать новый пароль. Если же администратор не будет менять пароля, то можно использовать пароль по умолчанию, " masterkey " (или ваш вариант).
  3. Удаление любого пользователя, кроме SYSDBA.

Для реализации этой задачи создадим новую вкладку, которую назовем TSh3, а в свойстве Caption напишем "Пользователи". Внешний вид вкладки показан на следующем рисунке:

Вкладка "Пользователи"

Рис. 27.3 . Вкладка "Пользователи"

Здесь мы установили компонент ListBox, свойство Name которого переименовали в LB1, а свойство Align перевели в alLeft, чтобы компонент занял всю левую часть окна. Измените размеры компонента, как на рисунке.

В правой части установили три простых кнопки Button. Свойства Name кнопок переименовали в bAddUser, bModifyUser и bDeleteUser, а в свойстве Caption, соответственно, прописали "Добавить", "Редактировать" и "Удалить".

Кроме того, мы добавили не визуальный компонент IBSecurityService с вкладки InterBase Admin. Компонент для краткости обращения переименовали в IBSS. Этот компонент предназначен для работы с пользователями, зарегистрированными в InterBase, и позволит нам редактировать, добавлять и удалять пользователей.

Несмотря на кажущуюся простоту окна, реализация работы с пользователями немного сложнее предыдущих примеров. В отличие от компонентов IBBackupService и IBRestoreService, компонент IBSecurityService выполняет не одну, а три задачи, что выражено кнопками в правой части окна. Кроме того, IBSecurityService работает не с нашей базой данных first.gdb, а с системной БД InterBase isc4.gdb, что накладывает некоторые ограничения. Например, имя, отчество и фамилию пользователя не получится вносить русскими буквами, так как isc4.gdb создавалась не в кодировке WIN1251. Кроме того, в целях безопасности, компонент IBSecurityService не выводит существующий пароль пользователя, хотя и позволяет менять его. Компонент позволяет оперировать такими данными, как логин пользователя, его пароль, имя, отчество, фамилия, идентификатор пользователя UserID и идентификатор группы GroupID.

Для доступа к данным пользователя компонент IBSecurityService имеет свойство UserInfo, которое представляет собой список пользователей. Индекс свойства начинается с 0, как и список строк ListBox. Так как индексы ListBox.Items и IBSecurityService . UserInfo будут совпадать, это сильно облегчит нашу задачу.

Первым делом нам нужно при создании главной формы заполнить компонент IBSecurityService свежими данными о пользователях, и обновить этими данными список ListBox.Так как нам то же самое придется делать при добавлении, редактировании и удалении пользователей, в разделе private добавим новую процедуру ReloadUsers:

private
    { Private declarations }
    function GetName():String;
    procedure BackupCopy;
    procedure ReloadUsers;

Реализация этой процедуры:

{Перечитываем данные о пользователях}
procedure TfMain.ReloadUsers;
var i: Integer; //для счетчика
begin
  //вначале очистим ListBox:
  LB1.Clear;
  //заполняем список пользователями:
  IBSS.ServerName:= 'MyServ';
  IBSS.LoginPrompt:= False;
  IBSS.Params.Add('user_name=sysdba');
  IBSS.Params.Add('password=masterkey');
  IBSS.Active:= True;
  try
    IBSS.DisplayUsers; //получаем  информацию о пользователях
    for i:=0 to IBSS.UserInfoCount -1 do
      LB1.Items.Add(IBSS.UserInfo[i].UserName);
  finally
    IBSS.Active:= False;
  end; //try
end;

Здесь все достаточно прозрачно. Вначале очищаем ListBox от возможных старых записей. Затем настраиваем сервис IBSecurityService, так же, как ранее настраивали компоненты IBRestoreService и IBBackupService.

Метод DisplayUsers получает в компонент всю информацию о пользователях, после чего она доступна в свойстве UserInfo. Свойство UserInfoCount показывает общее количество пользователей. Подсвойство UserName свойства UserInfo содержит логин текущего пользователя. Строкой

LB1.Items.Add(IBSS.UserInfo[i].UserName);

мы добавляем в ListBox имя очередного пользователя. Теперь нужно вызвать эту процедуру при создании формы. Для этого сгенерируйте для главной формы событие OnCreate, в котором сделаем вызов этой процедуры:

ReloadUsers;

Проверить результат можно, скомпилировав и загрузив программу. При загрузке, в окне ListBox должны отобразиться зарегистрированные пользователи.

Далее нам придется сделать новую форму - редактор данных пользователей. Выберите команду File -> New -> Form. Форму назовите fEditor, в свойстве Caption напишите "Редактирование данных пользователя", сохраните новый модуль под именем Editor.

Свойство BorderStyle формы переведем в bsDialog, чтобы пользователь не мог менять размеры окна, а в свойстве Position выберем poMainFormCenter.

Внешний вид новой формы показан на рисунке ниже:

Форма fEditor

Рис. 27.4 . Форма fEditor

Итак, у нас имеется:

  • Два компонента GroupBox.
  • Шесть компонентов Label.
  • Шесть компонентов Edit.
  • Две кнопки Button.

В свойстве Caption первого GroupBox напишем "Обязательные данные", а второго - "Дополнительные данные".

На верхний GroupBox помещаем три Label и заполняем текст, как на рисунке. Затем помещаем три Edit. У первого свойство Name переименуем в eUser, у второго - ePass, и у третьего - ePass2.

Выделите одновременно (с нажатой Shift ) компоненты ePass и ePass2. В свойстве PasswordChar укажите символ "*", чтобы скрыть реальный пароль. Не забудьте удалить текст из свойства Text всех компонентов Edit.

На нижний GroupBox также помещаем три Label и заполняем текст, как на рисунке. Затем помещаем три Edit. У первого свойство Name переименуем в eName, у второго - eMiddle, и у третьего - eLast. Очищаем свойство Text у всех Edit.

Ниже расположим две кнопки, которые переименуем соответственно, в bAccept и bCancel, а свойства Caption - как на рисунке.

Теперь немного подумаем. Эта форма будет показываться в двух случаях: при добавлении нового пользователя, и при редактировании существующего. В первом случае пользователь еще не имеет пароля, во втором - имеет. Причем при редактировании существующего пользователя, администратор может как сменить старый пароль, так и не трогать его. Как узнать, менялся ли пароль существующего пользователя, если мы не имеем возможности вывести его с помощью IBSecurityService? Вариант: при редактировании существующего пользователя поместим в ePass и ePass 2 какой-нибудь длинный пароль "по умолчанию", например, двадцать единичек. А при сохранении результата редактирования будем смотреть - если в ePass пароль "по умолчанию", значит сохранять пароль не нужно. В случае же добавления нового пользователя ePass и ePass2 заполняться не будут.

Пойдем дальше. Как уже говорилось, база данных isc4.gdb не поддерживает кодировку win1251, следовательно, русские буквы в нее помещать нельзя. Значит, при вводе текста во все шесть компонентов Edit придется делать проверку - что вводит пользователь. Если английские буквы или цифры, или BackSpace, то ничего не делаем, иначе запрещаем символ. Чтобы шесть раз не писать один и тот же код, в разделе private создадим функцию KeyCan:

private
    { Private declarations }
    function KeyCan(c:Char):Boolean;

Код реализации функции представлен ниже:

{Проверяем допустимость символа}
function TfEditor.KeyCan(c: Char): Boolean;
begin
  case c of
    'A'..'z': Result:= True; //англ. буквы разрешаем
    '0'..'9': Result:= True; //цифры разрешаем
    #8 : Result:= True; //BackSpace разрешаем
  else Result:= False; //остальное запрещаем
  end; //case
end;

Теперь нам нужно реализовать проверку во всех шести Edit. Выделите первый, и сгенерируйте для него событие OnKeyPress. В процедуру поместите только одну строку:

if not KeyCan(Key) then Key:= #0;

То же самое проделайте с оставшимися пятью Edit. Таким образом, мы реализовали проверку на ввод допустимых символов. Если пользователь попытается ввести что-нибудь, кроме английских букв, цифр или BackSpace, то его действия будут игнорироваться.

Пойдем дальше. Если мы редактируем нового пользователя, то в ePass и ePass2 у нас будет текст в двадцать единиц. Если администратор захочет изменить пароль, то он изменит текст в ePass. Значит, для ePass нужно сгенерировать событие OnChange, в котором очищаем текст у ePass2:

ePass2.Text:= '';

Теперь подумаем вот о чем. Окно редактора пользователей мы будем вызывать из главной формы, там же мы будем сохранять изменения, если администратор нажмет кнопку "Подтвердить" в окне редактора. А как из главной формы узнать - хочет ли администратор сохранить изменения, или нет? Введем глобальную переменную izmen в модуль редактора пользователей:

var
  fEditor: TfEditor;
  izmen: Boolean;

Теперь для формы редактора пользователей сгенерируем событие OnShow, в котором сразу пропишем:

izmen:= False;

В событии нажатия на кнопку "Подтвердить" вписываем код:

izmen:= True;
  Close;

А при нажатии на кнопку "Отменить" просто закрываем форму:

Close;

Теперь, если администратор закроет эту форму иначе, чем нажатием на "Подтвердить", мы ничего предпринимать не будем. Осталось сделать проверки на то, ввел ли администратор логин нового пользователя, совпадают ли пароли в ePass и ePass2? Для этого сгенерируем событие OnClose для формы редактора:

{при закрытии формы}
procedure TfEditor.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //если изменения не нужно делать, просто выходим:
  if not izmen then Exit;
  //Иначе делаем проверку. Если нет имени пользователя:
  if eUser.Text = '' then begin
    ShowMessage('Введите имя пользователя!');
    Action := caNone; //запрещаем покидать форму
    eUser.SetFocus; //переводим фокус на имя пользователя
  end;
  //Если пароль не '11111111111111111111', делаем проверку
  //совпадает ли ePass и ePass2:
  if ePass.Text <> '11111111111111111111' then
    if ePass.Text <> ePass2.Text then begin
      ShowMessage('Введите правильный пароль!');
      Action := caNone; //запрещаем покидать форму
      //очистим ePass и ePass2:
      ePass.Text:= '';
      ePass2.Text:= '';
      ePass.SetFocus; //переводим фокус на имя пользователя
    end;
end;

Комментарии достаточно подробны, чтобы вы смогли разобраться с кодом.

С этой формой закончили, вернемся на главную форму. Не забудем сразу же командой File -> Use Unit подключить к ней модуль Editor.

< Лекция 26 || Лекция 27: 12345 || Лекция 28 >
Евгений Медведев
Евгений Медведев

В лекции №2 вставляю модуль данных. При попытке заменить name на  fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? 

Анна Зеленина
Анна Зеленина

При вводе типов успешно сохраняется только 1я строчка. При попытке ввести второй тип вылезает сообщение об ошибке "project mymenu.exe raised exception class EOleException with message 'Microsoft Драйвер ODBC Paradox В операции должен использоваться обновляемый запрос'. 

Денис Попов
Денис Попов
Россия, Оренбург, Оренбургский государственный университет, 2015
Рустам Кадыров
Рустам Кадыров
Россия, Тирлян, Тирлянская школа №5, 2003