Viewing file: userWindow.py (16.4 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
## userWindow.py - event handling code for userconf's user window ## Copyright (C) 2001-2003 Red Hat, Inc. ## Copyright (C) 2001-2003 Brent Fox <bfox@redhat.com>
## 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 2 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, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
## Author: Brent Fox
import gtk import string import libuser import mainWindow import messageDialog import userGroupCheck import userGroupFind
## ## I18N ## from rhpl.translate import _, N_ import rhpl.translate as translate domain = "system-config-users" translate.textdomain (domain) gtk.glade.bindtextdomain(domain)
busy_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH) ready_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
class userWindow:
def __init__(self, parent, userStore, group_clist, xml, selinuxEnabled): self.parent = parent self.userStore = userStore self.group_clist = group_clist self.userWin = xml.get_widget('newUserWindow') self.userWin.connect("delete-event", self.on_userWin_cancel_button_clicked) self.userWin.set_icon(mainWindow.iconPixbuf) self.userWinUserName = xml.get_widget('newUserNameEntry') self.userWinFullName = xml.get_widget('newFullNameEntry') self.userWinPassword = xml.get_widget('newPasswordEntry') self.userWinConfirm = xml.get_widget('newConfirmEntry') self.userWinHomeDir = xml.get_widget('newHomeDirEntry') self.loginShellCombo = xml.get_widget('newLoginShellCombo') self.loginShellCombo.entry.set_property('editable', False) self.selinuxCombo = xml.get_widget("selinuxCombo") self.selinuxCombo.entry.set_property('editable', False) self.selinuxLabel = xml.get_widget("selinuxLabel") self.newGroupCheck = xml.get_widget('newGroupCheck') self.passwordLabel = xml.get_widget('passwordLabel') self.homeDirHbox = xml.get_widget('homeDirHbox') self.homeDirCheck = xml.get_widget('homeDirCheck') self.uidCheckButton = xml.get_widget('uidCheckButton') self.uidBox = xml.get_widget('uidBox') self.uidSpinButton = xml.get_widget('uidSpinButton') self.uidSpinButton.set_range(0, pow(2, 32)) self.uidSpinButton.set_value(500)
if not selinuxEnabled: self.selinuxCombo.set_sensitive(False) self.selinuxLabel.set_sensitive(False)
self.selinuxRoleDict = { _("User"): "user_r", _("Staff") : "staff_r", _("System Administrator") : "sysadm_r"} roles = self.selinuxRoleDict.keys() roles.sort() self.selinuxCombo.set_popdown_strings(roles) self.selinuxCombo.list.select_item(2)
self.shells = self.parent.ADMIN.getUserShells() self.shells.sort() self.loginShellCombo.set_popdown_strings(self.shells) default = '/bin/bash' if default in self.shells: self.loginShellCombo.list.select_item(self.shells.index(default))
xml.signal_connect("on_userWin_cancel_button_clicked", self.on_userWin_cancel_button_clicked) xml.signal_connect("on_userWin_ok_button_clicked", self.on_userWin_ok_button_clicked) xml.signal_connect("on_newUserNameEntry_focus_out_event", self.on_newUserNameEntry_focus_out_event) xml.signal_connect("on_uidCheckButton_toggled", self.on_uidCheckButton_toggled)
#--function to reset the entry widgets in the user screen def userWinReset(self): self.userWinUserName.grab_focus() self.userWinUserName.set_text("") self.userWinFullName.set_text("") self.userWinPassword.set_text("") self.userWinConfirm.set_text("") self.userWinHomeDir.set_text("") self.newGroupCheck.set_active(True) self.uidCheckButton.set_active(False) self.homeDirCheck.set_active(True) try: #Hack to work around what I suspect is a gtk bug self.uidSpinButton.set_value(500) except: pass
default = '/bin/bash' if default in self.shells: self.loginShellCombo.list.select_item(self.shells.index(default))
def busy(self): self.userWin.set_sensitive(False) self.userWin.window.set_cursor(busy_cursor)
def ready(self): self.userWin.window.set_cursor(ready_cursor) self.userWin.set_sensitive(True)
def newUserWin(self, filter): self.filter = filter self.userWinReset() self.userWin.show_all()
#Hide SELinux widgets for now self.selinuxCombo.hide() self.selinuxLabel.hide()
def hideWin(self): self.userWin.hide()
def getUserName(self): name = self.userWinUserName.get_text() return name
def getFullName(self): return self.userWinFullName.get_text()
#--------Event handlers for user window-----# def on_homeDirCheck_toggled(self, *args): self.homeDirHbox.set_sensitive(self.homeDirCheck.get_active())
def on_newUserNameEntry_focus_out_event(self, *args): name = self.userWinUserName.get_text() self.userWinHomeDir.set_text("/home/%s" % name)
def on_uidCheckButton_toggled(self, *args): self.uidBox.set_sensitive(self.uidCheckButton.get_active())
def on_userWin_cancel_button_clicked(self, *args): self.userWinReset() self.userWin.hide() return True
def on_userWin_ok_button_clicked(self, *args): self.busy() userName = self.userWinUserName.get_text() fullName = self.userWinFullName.get_text() pw = self.userWinPassword.get_text () confirm = self.userWinConfirm.get_text () homeDir = self.userWinHomeDir.get_text()
#Check for ascii-only strings if not userGroupCheck.isUsernameOk(userName, self.userWinUserName): self.ready() self.userWinUserName.grab_focus() return
if not userGroupCheck.isNameOk(fullName, self.userWinFullName): self.ready() self.userWinFullName.grab_focus() return
if not userGroupCheck.isPasswordOk(pw, self.userWinPassword): self.ready() self.userWinPassword.grab_focus() return
if not userGroupCheck.isPasswordOk(confirm, self.userWinConfirm): self.ready() self.userWinConfirm.grab_focus() return
if not userGroupCheck.isHomedirOk(homeDir, self.userWinHomeDir): self.ready() self.userWinHomeDir.grab_focus() self.on_newUserNameEntry_focus_out_event() return
if userName == "": #The user name is blank, so complain messageDialog.show_message_dialog(_("Please specify a user name")) self.ready() self.userWinUserName.grab_focus() return
user = self.parent.ADMIN.lookupUserByName(userName) if user != None: #This user already exists, so complain messageDialog.show_message_dialog(_("An account with username '%s' already exists.") %userName) self.ready() self.userWinUserName.set_text("") self.userWinUserName.grab_focus() return
if pw == confirm and len (pw) >= 6: #If the passwords match, go on pass else: #The passwords don't match, so complain if not pw and not confirm: messageDialog.show_message_dialog(_("Please enter a password for the user.")) self.ready() self.userWinPassword.set_text("") self.userWinConfirm.set_text("") self.userWinPassword.grab_focus() return
elif len (pw) < 6: messageDialog.show_message_dialog(_("The password is too short. Please " "use at least 6 characters.")) self.ready() self.userWinPassword.set_text("") self.userWinConfirm.set_text("") self.userWinPassword.grab_focus() return
else: messageDialog.show_message_dialog(_("The passwords do not match.")) self.ready() self.userWinPassword.set_text("") self.userWinConfirm.set_text("") self.userWinPassword.grab_focus() return
userEnt = self.parent.ADMIN.initUser(userName) # workaround bug with purely numerical names in ADMIN.initUser () userEnt.set (libuser.USERNAME, userName) userEnt.set(libuser.GECOS, [fullName]) # Don't set if there are defaults if not len (userEnt.get (libuser.SHADOWMIN)): userEnt.set(libuser.SHADOWMIN, '0') if not len (userEnt.get (libuser.SHADOWMAX)): userEnt.set(libuser.SHADOWMAX, '99999')
if self.homeDirCheck.get_active(): userEnt.set(libuser.HOMEDIRECTORY, [homeDir]) else: userEnt.set(libuser.HOMEDIRECTORY, [""]) userEnt.set(libuser.LOGINSHELL, [self.loginShellCombo.entry.get_text()])
if self.uidCheckButton.get_active(): uidNumber = int(self.uidSpinButton.get_value()) else: uidNumber = None
gidNumber = None gidDuplicate = False
try: uidNumber, gidNumber = userGroupFind.find_uid_gid (self.parent.ADMIN, self.parent.preferences, uidNumber = uidNumber, gidNumber = gidNumber) except userGroupFind.DuplicateUidNumberError, ue: # This uid already exists, so complain messageDialog.show_message_dialog(_("The uid %s is already in use.") % ue.uidNumber) self.ready() self.uidSpinButton.grab_focus() return except userGroupFind.DuplicateGidNumberError, ge: gidDuplicate = True gidNumber = ge.gidNumber # A group with this gid already exists. Handle this a little further down.
if self.uidCheckButton.get_active() and uidNumber < 500: # They want a UID < 500. Warn the user, but allow it if they insist dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, (_("Creating a user with a UID less than 500 is not recommended. " "Are you sure you want to do this?"))) dlg.set_position(gtk.WIN_POS_CENTER) dlg.set_modal(True) dlg.set_icon(mainWindow.iconPixbuf) result = dlg.run() dlg.destroy()
if result == gtk.RESPONSE_YES: pass else: self.ready() return
userEnt.set(libuser.UIDNUMBER, [uidNumber])
if self.newGroupCheck.get_active(): #Create new group
group = self.parent.ADMIN.lookupGroupByName(userName) if group != None or gidDuplicate: # A group with this name or gid already exists. Ask them what they want to do. dlg = gtk.Dialog() dlg.set_modal(True) dlg.set_icon(mainWindow.iconPixbuf) dlg.add_button(gtk.STOCK_CANCEL, 0) dlg.add_button(gtk.STOCK_OK, 1) dlg.set_border_width(4) dlg.vbox.set_spacing(4)
if gidDuplicate: label = gtk.Label(_("A group with this gid already exists. What would you like to do?")) else: label = gtk.Label(_("A group with this name already exists. What would you like to do?")) label.set_line_wrap(True) dlg.vbox.pack_start(label)
self.existingRadio = gtk.RadioButton(None, (_("Add to the existing group"))) self.usersRadio = gtk.RadioButton(self.existingRadio, (_("Add to the 'users' group"))) self.existingRadio.set_border_width(6) self.usersRadio.set_border_width(6) dlg.vbox.pack_start(self.existingRadio) dlg.vbox.pack_start(self.usersRadio) dlg.show_all() result = dlg.run() dlg.destroy()
if result == 1: #The clicked Ok, so do what they want if self.existingRadio.get_active(): #Add the user to the existing group if gidDuplicate: cn = [userName, self.parent.ADMIN.lookupGroupById (gidNumber)] else: cn = group.get(libuser.GROUPNAME)[0] #gidNumber = group.get(libuser.GIDNUMBER)[0] userEnt.set(libuser.GIDNUMBER, [gidNumber]) self.userWinReset() self.userWin.hide() else: #Add the user to the 'users' group self.addToUsersGroup(userEnt, userName) self.userWinReset() self.userWin.hide() else: #They clicked Cancel, so do nothing self.ready() return
else: #No group currently exists with this name, so we can create one groupEnt = self.parent.ADMIN.initGroup(userName) # workaround bug with purely numerical names in ADMIN.initGroup () groupEnt.set (libuser.GROUPNAME, userName) groupEnt.set (libuser.GIDNUMBER, gidNumber) cn = groupEnt.get(libuser.GROUPNAME)[0]
userEnt.set(libuser.GIDNUMBER, [gidNumber]) members = groupEnt.get(libuser.MEMBERNAME) if not members: members = [] memberlist = string.join(members, ", ")
self.parent.ADMIN.addGroup(groupEnt) self.parent.refresh_users_and_groups(cn) self.userWinReset() self.userWin.hide()
else: #Add user to group 'users' self.addToUsersGroup(userEnt, userName) self.userWin.hide()
if self.homeDirCheck.get_active(): #Create a home directory for the user self.parent.ADMIN.addUser(userEnt) else: #Do not create a home directory for the user self.parent.ADMIN.addUser(userEnt) homeDir = ""
self.parent.ADMIN.setpassUser(userEnt, pw, 0) self.parent.refresh_users_and_groups([userName, 'users']) self.ready()
def addToUsersGroup(self, userEnt, userName): groupEnt = self.parent.ADMIN.lookupGroupByName('users')
if groupEnt == None: #The 'users' doesn't exist. Let's create one groupEnt = self.parent.ADMIN.initGroup('users') groupEnt.set(libuser.GIDNUMBER, "100") self.parent.ADMIN.addGroup(groupEnt) cn = groupEnt.get(libuser.GROUPNAME)[0] # try to get a name to associate with the user's primary gid, # and attempt to minimize lookups by caching answers try: gidNumber = groupEnt.get(libuser.GIDNUMBER)[0] except: #Uh-oh. It looks like /etc/group and /etc/gshadow are out of sync. Give up and quit. messageDialog.show_message_dialog(_("The system group database cannot be read. This problem is most likely caused by a mismatch in /etc/group and /etc/gshadow. The program will exit now.")) import os os._exit(0)
userEnt.set(libuser.GIDNUMBER, [gidNumber])
members = groupEnt.get(libuser.MEMBERNAME) if not members: members = []
members.append(userName) groupEnt.set(libuser.MEMBERNAME, members) self.parent.ADMIN.modifyGroup(groupEnt)
|