]> scripts.mit.edu Git - wizard.git/blob - wizard/user.py
Set admin e-mail address properly on MediaWiki >= 1.18.0
[wizard.git] / wizard / user.py
1 """
2 Module for querying information about users.  This mostly asks plugins
3 for the extra information, and falls back to using a default that should
4 work on most systems (but by no means all systems.)
5 """
6
7 import pkg_resources
8 import os
9 import socket
10 import logging
11 import pwd
12
13 from wizard import plugin
14
15 def quota(dir=None):
16     """
17     Returns a tuple (quota usage, quota limit).  Returns ``None`` if
18     the quota usage is unknown.  If ``dir`` is omitted, the current
19     working directory is assumed.  Value returned is in bytes.
20
21     This function implements a plugin interface named
22     :ref:`wizard.user.quota`.
23     """
24     if dir is None:
25         dir = os.getcwd()
26     return plugin.hook("wizard.user.quota", [dir])
27
28 def email(name=None):
29     """
30     Converts a username into an email address to that user.  If you have
31     a UID, you will have to convert it into a username first.  If no
32     canonical source of information is found, an heuristic approach
33     will be used.  If ``name`` is ``None``, the current user will be
34     used unless it is root, in which case :func:`operator` is tried
35     first to determine the real current user.
36
37     This function implements a plugin interface named
38     :ref:`wizard.user.email`.
39     """
40     if name is None:
41         logging.info("wizard.user.email: Determining email for current user")
42         env_email = os.getenv("EMAIL")
43         if env_email is not None:
44             logging.info("wizard.user.email: Used environment email %s", env_email)
45             return env_email
46         name = operator()
47     # run plugins
48     r = plugin.hook("wizard.user.email", [name])
49     if r is not None:
50         return r
51     # guess an email
52     try:
53         mailname = open("/etc/mailname").read()
54     except:
55         mailname = socket.getfqdn()
56     return name + "@" + mailname
57
58 def operator():
59     """
60     Determines the username of the true person who is running this
61     program.  If the process's real uid is nonzero, just do a passwd
62     lookup; otherwise attempt to figure out the user behind the root
63     prompt some other way.
64
65     This function implements a plugin interface named
66     :ref:`wizard.user.operator`.
67     """
68     uid = os.getuid()
69     if uid:
70         pwdentry = pwd.getpwuid(uid)
71         return pwdentry.pw_name
72     # run plugins
73     r = plugin.hook("wizard.user.operator", [])
74     if r is not None:
75         return r
76     # use SUDO_USER
77     sudo_user = os.getenv("SUDO_USER")
78     if not sudo_user:
79         return None
80     pwdentry = pwd.getpwnam(sudo_user)
81     return pwdentry.pw_name
82
83 def passwd(path=None, uid=None):
84     """
85     Returns a passwd-like entry (a :class:`Info` object) corresponding
86     to the owner of ``path``.  If ``uid`` is specified, ``path`` is used
87     solely to determine the filesystem ``uid`` was determined from.  It
88     will fall back to the local passwd database, and return ``None``
89     if no information is available.  If ``path`` is omitted, it will
90     fall back to the current working directory.
91
92     This function implements a plugin interface named
93     :ref:`wizard.user.passwd`.
94     """
95     if path is None:
96         path = os.getcwd()
97     path = os.path.realpath(path)
98     if not uid:
99         uid = os.stat(path).st_uid
100     r = plugin.hook("wizard.user.passwd", [path, uid])
101     if r is not None:
102         return r
103     try:
104         return Info.pwentry(pwd.getpwuid(uid))
105     except KeyError:
106         return None
107
108 def pwnam(name):
109     """
110     This user converts a username into a :class:`Info` object using
111     *only* the local password database.
112     """
113     return Info.pwentry(pwd.getpwnam(name))
114
115 class Info(object):
116     """
117     Object containing information describing a user.  It is analogous to
118     passwd, but has dropped the password field and dedicated the
119     ``gecos`` field for real name information.
120
121     .. note::
122
123         If a platform does not support retrieving information about a
124         field, it may have the value ``None``.
125     """
126     #: Login name
127     name = None
128     #: User ID
129     uid = None
130     #: Group ID
131     gid = None
132     #: Real name
133     realname = None
134     #: Home directory
135     homedir = None
136     #: Default command interpreter
137     shell = None
138     @staticmethod
139     def pwentry(pwentry):
140         return Info(pwentry.pw_name, pwentry.pw_uid, pwentry.pw_gid,
141                 pwentry.pw_gecos.split(",")[0], pwentry.pw_dir, pwentry.pw_shell)
142     def __init__(self, name, uid, gid, realname, homedir, shell):
143         self.name = name
144         self.uid = uid
145         self.gid = gid
146         self.realname = realname
147         self.homedir = homedir
148         self.shell = shell
149         self._email = None
150     @property
151     def email(self):
152         """The email of this user, calculated on the fly."""
153         if self._email is None:
154             self._email = email(self.name)
155         return self._email