В лекции №2 вставляю модуль данных. При попытке заменить name на fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? |
Программное администрирование баз данных InterBase
Работа с пользователями
Определимся с задачей:
- Добавление нового пользователя.
- Изменение данных существующего пользователя (пароль, имя, отчество, фамилия). Если пользователь - SYSDBA, редактирование запрещаем. Ведь при резервном копировании и восстановлении мы жестко задавали имя SYSDBA и пароль masterkey (если вы изменили этот пароль, значит у вас свой вариант). И если администратор изменит этот пароль, программа не сможет работать, вам придется изменить этот пароль в программе и перекомпилировать ее. Впрочем, в дальнейшем вы можете усложнить программу, добавив в нее, например, работу с ini -файлом (см. "Ключи и индексы" курса "Введение в программирование на Delphi "). В этом случае, вы сможете прописать в ini -файл новый пароль пользователя SYSDBA, если администратор изменит его, и в дальнейшем использовать новый пароль. Если же администратор не будет менять пароля, то можно использовать пароль по умолчанию, " masterkey " (или ваш вариант).
- Удаление любого пользователя, кроме SYSDBA.
Для реализации этой задачи создадим новую вкладку, которую назовем TSh3, а в свойстве Caption напишем "Пользователи". Внешний вид вкладки показан на следующем рисунке:
Здесь мы установили компонент 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.
Внешний вид новой формы показан на рисунке ниже:
Итак, у нас имеется:
- Два компонента 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.