[sabayon: 4/19] Refactored userdb into systemdb
- From: Scott Balneaves <sbalneav src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [sabayon: 4/19] Refactored userdb into systemdb
- Date: Fri, 4 Dec 2009 20:57:16 +0000 (UTC)
commit 87ee462dc28201af9f43c0b163e790e5471826de
Author: Scott Balneaves <sbalneav ltsp org>
Date: Wed Sep 2 23:18:34 2009 -0500
Refactored userdb into systemdb
admin-tool/groupsdialog.py | 4 +-
admin-tool/profilesdialog.py | 9 +-
admin-tool/sabayon-apply | 6 +-
admin-tool/usersdialog.py | 4 +-
lib/Makefile.am | 3 +-
lib/groupdb.py | 486 ----------------------------------------
lib/{userdb.py => systemdb.py} | 202 +++++++++++++----
lib/unittests.py | 2 +-
8 files changed, 165 insertions(+), 551 deletions(-)
---
diff --git a/admin-tool/groupsdialog.py b/admin-tool/groupsdialog.py
index ab3f524..a7676b6 100644
--- a/admin-tool/groupsdialog.py
+++ b/admin-tool/groupsdialog.py
@@ -20,7 +20,7 @@ import os.path
import pwd
import gtk
import gtk.glade
-import groupdb
+import systemdb
import errors
import debuglog
@@ -44,7 +44,7 @@ class GroupsModel (gtk.ListStore):
class GroupsDialog:
def __init__ (self, profile, parent):
self.profile = profile
- self.groupdb = groupdb.get_database ()
+ self.groupdb = systemdb.get_group_database ()
apply_to_all = self.groupdb.get_default_profile (False) == profile
diff --git a/admin-tool/profilesdialog.py b/admin-tool/profilesdialog.py
index 3f16916..70f3765 100755
--- a/admin-tool/profilesdialog.py
+++ b/admin-tool/profilesdialog.py
@@ -30,8 +30,7 @@ import editorwindow
import usersdialog
import groupsdialog
import util
-import userdb
-import groupdb
+import systemdb
import protosession
import debuglog
import errors
@@ -261,7 +260,7 @@ class ProfilesModel (gtk.ListStore):
def reload (self):
self.clear ()
- profiles = userdb.get_database ().get_profiles ()
+ profiles = systemdb.get_user_database ().get_profiles ()
profiles.sort ()
for profile in profiles:
self.set (self.append (),
@@ -464,7 +463,7 @@ class ProfilesDialog:
dprint ("Deleting '%s'", profile_name)
os.remove (_get_profile_path_for_name (profile_name))
- db = userdb.get_database ()
+ db = systemdb.get_user_database ()
if db.get_default_profile (False) == profile_name:
db.set_default_profile (None)
for user in db.get_users ():
@@ -495,7 +494,7 @@ class ProfilesDialog:
self.__delete_currently_selected ()
def __make_unique_profile_name (self, profile_name):
- profiles = userdb.get_database ().get_profiles ()
+ profiles = systemdb.get_user_database ().get_profiles ()
name = profile_name
idx = 1
diff --git a/admin-tool/sabayon-apply b/admin-tool/sabayon-apply
index ecab0ce..62e86d0 100755
--- a/admin-tool/sabayon-apply
+++ b/admin-tool/sabayon-apply
@@ -42,7 +42,7 @@ if __name__ == '__main__':
from sabayon import debuglog
from sabayon import errors
from sabayon import util
- from sabayon import userdb
+ from sabayon import systemdb
def dprint (fmt, *args):
debuglog.debug_log (False, debuglog.DEBUG_LOG_DOMAIN_SABAYON_APPLY, fmt % args)
@@ -82,7 +82,7 @@ if __name__ == '__main__':
user_name = util.get_user_name ()
- if userdb.get_database().is_sabayon_controlled (user_name):
+ if systemdb.get_user_database().is_sabayon_controlled (user_name):
try:
shutil.rmtree (os.path.join (util.get_home_dir (), ".gconf.xml.defaults"), True)
shutil.rmtree (os.path.join (util.get_home_dir (), ".gconf.xml.mandatory"), True)
@@ -93,7 +93,7 @@ if __name__ == '__main__':
num_args = len (args)
if num_args == 0:
- profile_name = userdb.get_database().get_profile (user_name)
+ profile_name = systemdb.get_user_database().get_profile (user_name)
if not profile_name:
mprint ("No profile for user '%s' found", user_name)
sys.stderr.write (_("No profile for user '%s' found\n") % user_name)
diff --git a/admin-tool/usersdialog.py b/admin-tool/usersdialog.py
index 564619e..a22d4de 100644
--- a/admin-tool/usersdialog.py
+++ b/admin-tool/usersdialog.py
@@ -20,7 +20,7 @@ import os.path
import pwd
import gtk
import gtk.glade
-import userdb
+import systemdb
import errors
import debuglog
@@ -53,7 +53,7 @@ class UsersModel (gtk.ListStore):
class UsersDialog:
def __init__ (self, profile, parent):
self.profile = profile
- self.userdb = userdb.get_database ()
+ self.userdb = systemdb.get_user_database ()
apply_to_all = self.userdb.get_default_profile (False) == profile
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 931c731..08cdf1a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -23,11 +23,10 @@ PYTHON_FILES = \
errors.py \
debuglog.py \
dirmonitor.py \
- groupdb.py \
mozilla_bookmarks.py \
protosession.py \
storage.py \
- userdb.py \
+ systemdb.py \
usermod.py \
userprofile.py \
util.py
diff --git a/lib/userdb.py b/lib/systemdb.py
similarity index 76%
rename from lib/userdb.py
rename to lib/systemdb.py
index 88c8806..9127008 100644
--- a/lib/userdb.py
+++ b/lib/systemdb.py
@@ -19,6 +19,7 @@
import sys
import string
import pwd
+import grp
import os
import libxml2
import config
@@ -29,6 +30,9 @@ import ldap
import socket
import debuglog
+#
+# Default empty config.
+#
defaultConf="""<profiles>
<default profile=""/>
</profiles>"""
@@ -72,10 +76,10 @@ def expand_string (string, attrs):
return res
-class UserDatabaseException (Exception):
+class SystemDatabaseException (Exception):
pass
-class UserDatabase:
+class SystemDatabase(object):
"""An encapsulation of the database which maintains an
association between users and profiles.
@@ -89,19 +93,20 @@ class UserDatabase:
an absolute path or a http/file URL.
"""
def __init__ (self, db_file = None):
- """Create a UserDatabase object.
+ """Create a SystemDatabase object.
- @db_file: an (optional) path which specifes the location
- of the database file. If not specified, the default
- location of /etc/desktop-profiles/users.xml is used.
+ @db_file: a mandatory path which specifes the location
+ of the database file. If only a file is specified, the
+ directory /etc/desktop-profiles is used.
"""
if db_file is None:
- file = os.path.join (config.PROFILESDIR, "users.xml")
+ raise SystemDatabaseException(_("No database file provided"))
elif db_file[0] != '/':
file = os.path.join (config.PROFILESDIR, db_file)
else:
file = db_file
- self.file = file;
+ self.file = file
+ self.xmlquery = None
self.modified = 0
dprint("New UserDatabase(%s) object\n" % self.file)
@@ -117,7 +122,7 @@ class UserDatabase:
if self.doc == None:
self.doc = libxml2.readMemory(defaultConf, len(defaultConf),
None, None,
- libxml2.XML_PARSE_NOBLANKS);
+ libxml2.XML_PARSE_NOBLANKS)
def __del__ (self):
if self.doc != None:
@@ -143,7 +148,7 @@ class UserDatabase:
try:
base = node.getBase(None)
if base != None and base != "" and \
- base != os.path.join (config.PROFILESDIR, "users.xml"):
+ base != self.file:
# URI composition from the base
ret = libxml2.buildURI(profile, base)
if ret[0] == '/':
@@ -277,8 +282,8 @@ class UserDatabase:
return self.__profile_name_to_location (profile, default)
- def get_profile (self, username, profile_location = True, ignore_default = False):
- """Look up the profile for a given username.
+ def gen_get_profile (self, searchterm, replace, profile_location = True, ignore_default = False):
+ """Look up the profile for a given searchterm.
@username: the user whose profile location should be
returned.
@@ -293,10 +298,10 @@ class UserDatabase:
@profile_location is False.
"""
user = None
- profile = self.__ldap_query ("profilemap", {"u":username, "h":socket.getfqdn()})
+ profile = self.__ldap_query ("profilemap", replace)
if not profile:
try:
- query = "/profiles/user[ name='%s']" % username
+ query = self.xmlquery % searchterm
user = self.doc.xpathEval(query)[0]
profile = user.prop("profile")
except:
@@ -311,7 +316,7 @@ class UserDatabase:
if not profile_location:
return profile
-
+
# TODO Check the resulting file path exists
return self.__profile_name_to_location (profile, user)
@@ -357,7 +362,7 @@ class UserDatabase:
self.modified = 0
def set_default_profile (self, profile):
- """Set the default profile to be used for all users.
+ """Set the default profile to be used in this database.
@profile: the location of the profile.
"""
@@ -374,32 +379,31 @@ class UserDatabase:
try:
profiles = self.doc.xpathEval("/profiles")[0]
except:
- raise UserDatabaseException(
+ raise SystemDatabaseException(
_("File %s is not a profile configuration") %
(self.file))
try:
default = profiles.newChild(None, "default", None)
default.setProp("profile", profile)
except:
- raise UserDatabaseException(
+ raise SystemDatabaseException(
_("Failed to add default profile %s to configuration") %
(profile))
self.modified = 1
if self.modified == 1:
self.__save_as()
- def set_profile (self, username, profile):
- """Set the profile for a given username.
+ def gen_set_profile (self, searchterm, child, profile):
+ """Set the profile for a given searchterm.
- @username: the user whose profile location should be
- set.
+ @searchterm: the term whose profile location should be set.
@profile: the location of the profile.
"""
if profile is None:
profile = ""
self.modified = 0
try:
- query = "/profiles/user[ name='%s']" % username
+ query = self.xmlquery % searchterm
user = self.doc.xpathEval(query)[0]
oldprofile = user.prop("profile")
if oldprofile != profile:
@@ -409,21 +413,40 @@ class UserDatabase:
try:
profiles = self.doc.xpathEval("/profiles")[0]
except:
- raise UserDatabaseException(
- _("File %s is not a profile configuration") %
- (self.file))
+ raise SystemDatabaseException(
+ _("File %s is not a profile configuration") % (self.file))
try:
- user = profiles.newChild(None, "user", None)
- user.setProp("name", username)
+ user = profiles.newChild(None, child, None)
+ user.setProp("name", searchterm)
user.setProp("profile", profile)
except:
- raise UserDatabaseException(
+ raise SystemDatabaseException(
_("Failed to add user %s to profile configuration") %
(username))
self.modified = 1
if self.modified == 1:
self.__save_as()
+ def gen_is_sabayon_controlled (self, searchterm, replace):
+ """Return True if user's configuration was ever under Sabayon's
+ control.
+ """
+ profile = self.__ldap_query ("profilemap", replace)
+
+ if profile:
+ return True
+
+ try:
+ query = self.xmlquery % searchterm
+ user = self.doc.xpathEval(query)[0]
+ except:
+ return False
+
+ if user:
+ return True
+
+ return False
+
def get_profiles (self):
"""Return the list of currently available profiles.
This is basically just list of zip files in
@@ -440,25 +463,26 @@ class UserDatabase:
# TODO: also list remote profiles as found in self.doc
return list
- def is_sabayon_controlled (self, username):
- """Return True if user's configuration was ever under Sabayon's
- control.
- """
- profile = self.__ldap_query ("profilemap", {"u":username, "h":socket.getfqdn()})
+class UserDatabase(SystemDatabase):
+ """Encapsulate a user mapping
+ """
+ def __init__ (self, db_file = None):
+ if db_file is None:
+ SystemDatabase.__init__(self, "users.xml")
+ else:
+ SystemDatabase.__init__(self, db_file)
- if profile:
- return True
-
- try:
- query = "/profiles/user[ name='%s']" % username
- user = self.doc.xpathEval(query)[0]
- except:
- return False
+ self.xmlquery = "/profiles/user[ name='%s']"
- if user:
- return True
+ def get_profile (self, username, profile_location = True, ignore_default = False):
+ return self.gen_get_profile(username, {"u":username,
+ "h":socket.getfqdn()}, profile_location, ignore_default)
- return False
+ def is_sabayon_controlled (self, username):
+ return self.gen_is_sabayon_controlled(username, {"u":username, "h":socket.getfqdn()})
+
+ def set_profile (self, username, profile):
+ return self.gen_set_profile (username, "user", profile)
def get_users (self):
"""Return the list of users on the system. These should
@@ -469,13 +493,15 @@ class UserDatabase:
try:
users = pwd.getpwall()
except:
- raise UserDatabaseException(_("Failed to get the user list"))
+ raise SystemDatabaseException(_("Failed to get the user list"))
for user in pwd.getpwall():
try:
# remove non-users
if user[2] < 500:
continue
+ if user[0] == "nobody":
+ continue
if user[0] in list:
continue
if user[6] == "" or string.find(user[6], "nologin") != -1:
@@ -487,26 +513,85 @@ class UserDatabase:
pass
return list
+class GroupDatabase(SystemDatabase):
+ """Encapsulate a user mapping
+ """
+ def __init__ (self, db_file = None):
+ if db_file is None:
+ SystemDatabase.__init__(self, "groups.xml")
+ else:
+ SystemDatabase.__init__(self, db_file)
+
+ self.xmlquery = "/profiles/group[ name='%s']"
+
+ def get_profile (self, groupname, profile_location = True, ignore_default = False):
+ return self.gen_get_profile(groupname, {"g":groupname,
+ "h":socket.getfqdn()}, profile_location, ignore_default)
+
+ def is_sabayon_controlled (self, groupname):
+ return self.gen_is_sabayon_controlled(groupname, {"g":groupname, "h":socket.getfqdn()})
+ def set_profile (self, groupname, profile):
+ return self.gen_set_profile (groupname, "group", profile)
+
+ def get_groups (self):
+ """Return the list of groups on the system. These should
+ be real groups - i.e. should not include system groups
+ like lp, udev, etc.
+ """
+ list = []
+ try:
+ groups = grp.getgrall()
+ except:
+ raise GroupDatabaseException(_("Failed to get the group list"))
+
+ for group in groups:
+ # remove non-groups
+ if group[2] < 500:
+ continue
+ if group[0] == "nogroup":
+ continue
+ if group[0] in list:
+ continue
+ # We don't want to include "user" primary groups
+ try:
+ user = pwd.getpwnam(group[0])
+ except:
+ user = None
+ if user is not None and user[2] == group[2]:
+ continue
+ list.append(group[0])
+ return list
user_database = None
-def get_database ():
+group_database = None
+
+def get_user_database ():
"""Return a UserDatabase singleton"""
global user_database
if user_database is None:
user_database = UserDatabase ()
return user_database
+def get_group_database ():
+ """Return a UserDatabase singleton"""
+ global group_database
+ if group_database is None:
+ group_database = GroupDatabase ()
+ return group_database
#
# Unit tests
#
+
def run_unit_tests ():
- testfile = "/tmp/test_users.xml"
+ testuserfile = "/tmp/test_users.xml"
+ testgroupfile = "/tmp/test_groups.xml"
try:
- os.unlink(testfile)
+ os.unlink(testuserfile)
+ os.unlink(testgroupfile)
except:
pass
- db = UserDatabase(testfile)
+ db = UserDatabase(testuserfile)
db.set_default_profile("default")
res = db.get_profile("localuser", False)
assert not res is None
@@ -519,6 +604,23 @@ def run_unit_tests ():
res = db.get_profile("localuser")
assert not res is None
assert res[-28:] == "/desktop-profiles/groupB.zip"
+ res = db.get_users()
+ print res
+ db = GroupDatabase(testgroupfile)
+ db.set_default_profile("default")
+ res = db.get_profile("localuser", False)
+ assert not res is None
+ assert res == "default"
+ db.set_profile("localgroup", "groupA")
+ res = db.get_profile("localgroup")
+ assert not res is None
+ assert res[-28:] == "/desktop-profiles/groupA.zip"
+ db.set_profile("localgroup", "groupB")
+ res = db.get_profile("localgroup")
+ assert not res is None
+ assert res[-28:] == "/desktop-profiles/groupB.zip"
+ res = db.get_groups()
+ print res
if __name__ == "__main__":
util.init_gettext ()
diff --git a/lib/unittests.py b/lib/unittests.py
index 989ad68..2e491bf 100755
--- a/lib/unittests.py
+++ b/lib/unittests.py
@@ -39,7 +39,7 @@ if __name__ == "__main__":
( "paneldelegate", _("Ignore WARNINGs"), add_mod_dir, remove_mod_dir ),
( "mozillasource", None, add_mod_dir, remove_mod_dir ),
( "userprofile", None, None, None ),
- ( "userdb", None, None, None ),
+ ( "systemdb", None, None, None ),
( "cache", None, None, None )
]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]