Source

controlcenter / user_add / user_add.py

Full commit
#!/usr/bin/env python

#    This file is part of controlcenter.
#
#    controlcenter is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License v2 as published by
#    the Free Software Foundation.
#
#    controlcenter 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 controlcenter.  If not, see <http://www.gnu.org/licenses/>.


__author__ = 'Moises Henriquez'
__author_email__ = 'moc.liamg]ta[xnl.E0M'.replace(']ta[', '@')[::-1]

import gtk
import os

n_account = None
_tabs = []

class Account(object):
    '''Object for a user account. This object will have several properties
    available. These will be all set to None on a new account, or will
    default to the stored values on an existing account.
    '''
    def __init__(self):
        self.name = None
        self.homedir = None
        self.uid = None
        self.shell = None
        self.password = None
        self.maingroup = None
        self.groups = None
        self.login = None
    
    def load(self, login):
        '''Load the information stored in the system about a user account.
        Required arguments:
            login = String representing a valid user name in the system.
        '''
        passfile = '/etc/passwd'
        groupfile = '/etc/group'
        self.login = login
        f = open(passfile, 'r')
        passinfo = f.readlines()
        f.close()
        for line in passinfo:
            if line.startswith(login):
                spl = line.split(':')
                uid = spl[2]
                gid = spl[3]
                rname = spl[4]
                homedir = spl[5]
                shell = spl[6]
        self.uid = uid
        self.name = rname
        self.homedir = homedir
        self.shell = shell
        return
    


class MainWin(gtk.Window):
    '''Main window for user add module'''
    def __init__(self):
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
        self.connect('destroy', gtk.main_quit)
        self.set_property('title', 'Create User Account')
        body = gtk.VBox()
        self.add(body)
        self.tabstrip = gtk.Notebook()
        btnbar = gtk.HBox()
        
        body.pack_start(self.tabstrip, True, True, 4)
        body.pack_start(btnbar, False, False, 4)
        
        bt_OK = gtk.Button('OK', gtk.STOCK_OK)
        bt_Cancel = gtk.Button('Cancel', gtk.STOCK_CANCEL)
        bt_Cancel.connect('clicked', gtk.main_quit)
        
        btnbar.pack_end(bt_OK, False, False, 2)
        btnbar.pack_end(bt_Cancel, False, False, 2)

        self.set_default_size(400,450)
        self.set_position(gtk.WIN_POS_CENTER)

        ## Add Content to the window
        tab0 = BasicSettingsTab()
        self.tabstrip.append_page(tab0, tab0.label)
        _tabs.append(tab0)
        
        
        tab1 = PrivilegesTab()
        self.tabstrip.append_page(tab1, tab1.label)
        _tabs.append(tab1)
        
        adv = AdvancedTab()
        self.tabstrip.append_page(adv, adv.label)
        _tabs.append(adv)
    
    def load_account(self, account):
        self.n_account.load(account)
        
        
        
class Tab(gtk.VBox):
    '''Abstract class for a tab in the user add module 
    Required Arguments:
        title:  Title to be used for this tab
                Title is available after creating the object
                via tab.label and is returned as a gtk.Label'''
    def __init__(self, title):
        gtk.VBox.__init__(self)
        self.label = gtk.Label(title)
        
    def refresh_info(self):
        ''' This method can be called to refresh the information displayed
        in this tab. Information is read from the account object'''
        pass
    
    def load_existing_data(self):
        '''This method will read the data for an existing user account
        and display it on the tabstrip. This will allow the same tabstrip to be
        used when creating a new account as well as when editing an existing account'''
        pass

class SectionLabel(gtk.Label):
    '''Pre-set widget based on gtk.Label preformatted to be used as a
    section banner within tabs'''
    def __init__(self, text):
        gtk.Label.__init__(self)
        self.set_property('use-markup', True)
        self.set_property('label', '<b>%s</b>'%text)
        self.set_property('xalign', 0.0)
        self.set_property('xpad', 12)
        
class LineLabel(gtk.Label):
    '''Pre-set widget based on gtk.Label pre-formatted to be used as a 
    label in instances where a label is needed before another widget'''
    def __init__(self, text):
        gtk.Label.__init__(self)
        self.set_property('use-markup', True)
        self.set_property('label', text)
        self.set_property('xalign', 0.0)
        self.set_property('width-chars', 13)    ## Fixme: Fixed width for these?
        

class BasicSettingsTab(Tab):
    '''Tab displaying the basic settings for the user add module'''
    def load_existing_data(self):
        '''Loads the existing data about the user account to the appropriate widgets'''
        self.login_txt.set_text(n_account.login)
        self.login_txt.set_sensitive(False)
        self.name_txt.set_text(n_account.name)
        return
        
    def __init__(self):
        Tab.__init__(self, 'Basic Settings')
        banner = SectionLabel('Basic Information')
        self.pack_start(banner, False, False, 4)
        
        spacer = gtk.Label()
        self.pack_start(spacer, False, False, 4)
        line_name = gtk.HBox()
        login_label = LineLabel('Login Name')
        login_txtbox = gtk.Entry()
        self.login_txt = login_txtbox
        line_name.pack_start(login_label, False, False, 2)
        line_name.pack_start(login_txtbox, True, True, 2)
        self.pack_start(line_name, False, False, 4)
        
        rname_box = gtk.HBox()
        rname_label = LineLabel('Real Name')
        rname_txt = gtk.Entry()
        self.name_txt = rname_txt
        rname_box.pack_start(rname_label, False, False, 2)
        rname_box.pack_start(rname_txt, True, True, 2)
        self.pack_start(rname_box, False, False, 4)
        
        spacer = gtk.Label()
        self.pack_start(spacer, False, False, 4)
        
        banner1 = SectionLabel('Password')
        self.pack_start(banner1, False, False, 4)
        pass1_box = gtk.HBox()
        pass2_box = gtk.HBox()
        pass1_label = LineLabel('User Password')
        pass1_txt = gtk.Entry()
        self.pass1_box = pass1_txt
        pass1_txt.set_property('visibility', False)
        pass1_box.pack_start(pass1_label, False, False, 2)
        pass1_box.pack_start(pass1_txt, True, True, 2)
        
        pass2_label = LineLabel('Confirm Password')
        pass2_txt = gtk.Entry()
        self.pass2_box = pass2_txt
        pass2_txt.set_property('visibility', False)
        pass2_box.pack_start(pass2_label, False, False, 2)
        pass2_box.pack_start(pass2_txt, True, True, 2)
        
        self.pack_start(pass1_box, False, False, 4)
        self.pack_start(pass2_box, False, False, 4)
    

class PrivilegesTab(Tab):
    '''User privileges tab that allows the administrator to pick and choose what
    the user is allowed to do on the system'''
    def __init__(self):
        Tab.__init__(self, 'Privileges')
        banner = SectionLabel('User Privileges')
        self.pack_start(banner, False, False, 4)
        self.rights_values = [
        ('lpadmin', True,  'Manage system printers'), \
        ('scaner', False, 'Use scanners'), \
        ('video', True, 'Capture video from TV or webcam')
        ]
        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        tv = self._get_tree()
        sw.add(tv)
        self.pack_start(sw, True, True, 4)
    
    def _get_tree(self):
        '''Internal function that pvides a treeview with a list of
        checkbuttons to check off user access'''
        rights = self.rights_values
        store = gtk.ListStore(str, bool, str)
        for right in rights:
            store.append([right[0], right[1], right[2]])
        
        tree = gtk.TreeView(store)
        cell0 = gtk.CellRendererToggle()
        cell0.set_property('activatable', True)
        cell0.connect('toggled', self.checkbox_toggle, tree.get_model())
        col0 = gtk.TreeViewColumn(None, cell0)
        col0.add_attribute(cell0, 'active', 1)
        
        cell1 = gtk.CellRendererText()
        col1 = gtk.TreeViewColumn(None, cell1, text=2)
        tree.append_column(col0)
        tree.append_column(col1)
        
        return tree
    
    def checkbox_toggle(self, widget, path, model):
        model[path][1] = not model[path][1]


class AdvancedTab(Tab):
    '''Advanced settings tab.
    This tab will provide advanced settings for creating a user account.
    These settings are optional and default to the system defaults.
    '''
    def load_existing_data(self):
        self.homedir_box.set_text(n_account.homedir)
        self.homedir_box.set_sensitive(False)
        self.uid_spinner.set_value(float(n_account.uid))
        self.uid_spinner.set_sensitive(False)
        model = self.shell_sel_combo.get_model()
        n = 0
        for item in model:
            n += 1
        for x in range(0, n):
            if model[x][0].strip() == n_account.shell.strip():
                #print 'found %s in combobox. Setting as active'% n_account.shell.strip()
                self.shell_sel_combo.set_active(x)
                self.shell_sel_combo.set_sensitive(False) ## Fixme: Disabled for now
                break
        
    def __init__(self):
        Tab.__init__(self, 'Advanced')
        banner = SectionLabel('Advanced Settings')
        spacer = gtk.Label()
        self.pack_start(banner, False, False, 4)
        self.pack_start(spacer, False, False, 4)
        
        homedir_line = gtk.HBox()
        homedir_label = LineLabel('Home Directory')
        homedir_txt = gtk.Entry()
        self.homedir_box = homedir_txt
        homedir_line.pack_start(homedir_label, False, False, 2)
        homedir_line.pack_start(homedir_txt, True, True, 2)
        self.pack_start(homedir_line, False, False, 4)
        
        maingroup_line = gtk.HBox()
        maingroup_label = LineLabel('Main Group')
        ulist = gtk.ListStore(str)
        ## Read /etc/group and list all groups =< 100  <-- FIXME:
        f = open('/etc/group', 'r')
        glist = f.readlines()
        f.close()
        ulist.append(['Default (username)']) ## Defaults to user name
        for line in glist:
            spl = line.split(':')
            if int(spl[2]) > 0 and int(spl[2]) <= 100:
                ulist.append([spl[0].strip()])
        ## FIXME: ^^ User group policy?
        maingroup_sel = gtk.ComboBox(ulist)
        self.main_group_combo = maingroup_sel
        cell0 = gtk.CellRendererText()
        maingroup_sel.pack_start(cell0, True)
        maingroup_sel.add_attribute(cell0, 'text', 0)
        maingroup_sel.set_active(0)
        maingroup_line.pack_start(maingroup_label, False, False, 2)
        maingroup_line.pack_start(maingroup_sel, True, True, 2)
        self.pack_start(maingroup_line, False, False, 4)
        
        shell_line = gtk.HBox()
        shell_label = LineLabel('Login Shell')
        shell_list = gtk.ListStore(str)
        shell_sel = gtk.ComboBox(shell_list)

        self.shell_sel_combo = shell_sel
        
        ## Read /etc/shells if it exists to get the default shells available
        if os.path.exists('/etc/shells'):
            f = open('/etc/shells', 'r')
            shells = f.readlines()
            f.close()
            for shell in shells:
                shell_list.append([shell.strip()])
        elif os.path.exists('/bin/bash'):
            ## if /etc/shells doesn't exist, but /bin/bash does
            shell_list.append(['/bin/bash'])
        else:
            ## No shells available???
            shell_sel.set_sensitive(False)
        cell = gtk.CellRendererText()
        shell_sel.pack_start(cell, True)
        shell_sel.add_attribute(cell, 'text', 0)
        
        shell_sel.set_active(0)
        
        shell_line.pack_start(shell_label, False, False, 2)
        shell_line.pack_start(shell_sel, True, True, 2)
        self.pack_start(shell_line, False, False, 4)
        
        uid_line = gtk.HBox()
        uid_label = LineLabel('User ID')
        min_ = 1000
        n_list = []
        f = open('/etc/passwd', 'r')
        entries = f.readlines()
        f.close()
        for line in entries:
            spl = line.split(':')
            if int(spl[2]) >= 1000:
                n_list.append(int(spl[2]))
        n_list.sort()
        min_ = max(n_list)+1
        adj = gtk.Adjustment(1000, min_, 10000, 1, 10, 0)
        uid_spinner = gtk.SpinButton(adj, 0, 0)
        self.uid_spinner = uid_spinner
        uid_line.pack_start(uid_label, False, False, 2)
        uid_line.pack_start(uid_spinner, True, True, 2)
        self.pack_start(uid_line, False, False, 4)
    
if __name__ == '__main__':
    n_account = Account()
    w = MainWin()
    w.show_all()
    # Show account info for vluser
##    n_account.load('vluser')
##    w.set_title('Edit account vluser')
##    for tab in _tabs: tab.load_existing_data()
    gtk.main()