~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to lib/common/db.py

  • Committer: mattgiuca
  • Date: 2008-02-28 07:52:35 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:608
browser/listing: REMOVED the generation of all action links to the right
    panel. (Yes, this is the end of an era).
    Split the "Modified" stamp in the right panel to split over 3 lines so it
    takes up less horizontal space.
    Shrunk the right panel from 300px down to 200px, as requested by Steven
    Bird.
We can now rely solely on the top dropdown for doing actions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
import md5
37
37
import copy
38
38
 
39
 
from common import caps
 
39
from common import (caps, user)
40
40
 
41
41
def _escape(val):
42
42
    """Wrapper around pg.escape_string. Prepares the Python value for use in
140
140
        Raises a DBException if the dictionary contains invalid fields.
141
141
        """
142
142
        if not DB.check_dict(dict, tablefields, disallowed):
143
 
            raise DBException("Supplied dictionary contains invalid fields.")
 
143
            extras = set(dict.keys()) - tablefields
 
144
            raise DBException("Supplied dictionary contains invalid fields. (%s)" % (repr(extras)))
144
145
        # Build two lists concurrently: field names and values, as SQL strings
145
146
        fieldnames = []
146
147
        values = []
172
173
        """
173
174
        if (not (DB.check_dict(primarydict, primary_keys, must=True)
174
175
            and DB.check_dict(updatedict, tablefields, disallowed_update))):
175
 
            raise DBException("Supplied dictionary contains invalid or "
176
 
                " missing fields.")
 
176
            raise DBException("Supplied dictionary contains invalid or missing fields (1).")
177
177
        # Make a list of SQL fragments of the form "field = 'new value'"
178
178
        # These fragments are ALREADY-ESCAPED
179
179
        setlist = []
199
199
        primarydict, tablename, primary_keys: See update.
200
200
        """
201
201
        if not DB.check_dict(primarydict, primary_keys, must=True):
202
 
            raise DBException("Supplied dictionary contains invalid or "
203
 
                " missing fields.")
 
202
            raise DBException("Supplied dictionary contains invalid or missing fields (2).")
204
203
        wherelist = []
205
204
        for k,v in primarydict.items():
206
205
            wherelist.append("%s = %s" % (k, _escape(v)))
225
224
            primary_keys is indeed the primary key).
226
225
        """
227
226
        if not DB.check_dict(primarydict, primary_keys, must=True):
228
 
            raise DBException("Supplied dictionary contains invalid or "
229
 
                " missing fields.")
 
227
            raise DBException("Supplied dictionary contains invalid or missing fields (3).")
230
228
        wherelist = []
231
229
        for k,v in primarydict.items():
232
230
            wherelist.append("%s = %s" % (k, _escape(v)))
289
287
    login_primary = frozenset(["login"])
290
288
    login_fields_list = [
291
289
        "login", "passhash", "state", "unixid", "email", "nick", "fullname",
292
 
        "rolenm", "studentid", "acct_exp", "pass_exp", "last_login"
 
290
        "rolenm", "studentid", "acct_exp", "pass_exp", "last_login", "svn_pass"
293
291
    ]
294
292
    login_fields = frozenset(login_fields_list)
295
 
    # Do not return passhash when reading from the DB
296
 
    login_getfields = login_fields - frozenset(["passhash"])
297
293
 
298
 
    def create_user(self, dry=False, **kwargs):
 
294
    def create_user(self, user_obj=None, dry=False, **kwargs):
299
295
        """Creates a user login entry in the database.
 
296
        Two ways to call this - passing a user object, or passing
 
297
        all fields as separate arguments.
 
298
 
 
299
        Either pass a "user_obj" as the first argument (in which case other
 
300
        fields will be ignored), or pass all fields as arguments.
 
301
 
300
302
        All user fields are to be passed as args. The argument names
301
303
        are the field names of the "login" table of the DB schema.
302
304
        However, instead of supplying a "passhash", you must supply a
307
309
        invalid keys or is missing required keys.
308
310
        """
309
311
        if 'passhash' in kwargs:
310
 
            raise DBException("Supplied arguments include passhash (invalid).")
 
312
            raise DBException("Supplied arguments include passhash (invalid) (1).")
311
313
        # Make a copy of the dict. Change password to passhash (hashing it),
312
314
        # and set 'state' to "no_agreement".
313
 
        kwargs = copy.copy(kwargs)
314
 
        if 'password' in kwargs:
315
 
            kwargs['passhash'] = _passhash(kwargs['password'])
316
 
            del kwargs['password']
317
 
        kwargs['state'] = "no_agreement"
 
315
        if user_obj is None:
 
316
            # Use the kwargs
 
317
            fields = copy.copy(kwargs)
 
318
        else:
 
319
            # Use the user object
 
320
            fields = dict(user_obj)
 
321
        if 'password' in fields:
 
322
            fields['passhash'] = _passhash(fields['password'])
 
323
            del fields['password']
 
324
        if 'role' in fields:
 
325
            # Convert role to rolenm
 
326
            fields['rolenm'] = str(user_obj.role)
 
327
            del fields['role']
 
328
        if user_obj is None:
 
329
            fields['state'] = "no_agreement"
 
330
            # else, we'll trust the user, but it SHOULD be "no_agreement"
 
331
            # (We can't change it because then the user object would not
 
332
            # reflect the DB).
 
333
        if 'local_password' in fields:
 
334
            del fields['local_password']
318
335
        # Execute the query.
319
 
        return self.insert(kwargs, "login", self.login_fields, dry=dry)
 
336
        return self.insert(fields, "login", self.login_fields, dry=dry)
320
337
 
321
338
    def update_user(self, login, dry=False, **kwargs):
322
339
        """Updates fields of a particular user. login is the name of the user
333
350
        with a new one.
334
351
        """
335
352
        if 'passhash' in kwargs:
336
 
            raise DBException("Supplied arguments include passhash (invalid).")
 
353
            raise DBException("Supplied arguments include passhash (invalid) (2).")
337
354
        if "password" in kwargs:
338
355
            kwargs = copy.copy(kwargs)
339
356
            kwargs['passhash'] = _passhash(kwargs['password'])
343
360
            dry=dry)
344
361
 
345
362
    def get_user(self, login, dry=False):
346
 
        """Given a login, returns a dictionary of the user's DB fields,
347
 
        excluding the passhash field.
 
363
        """Given a login, returns a User object containing details looked up
 
364
        in the DB.
348
365
 
349
366
        Raises a DBException if the login is not found in the DB.
350
367
        """
351
 
        return self.get_single({"login": login}, "login",
352
 
            self.login_getfields, self.login_primary,
 
368
        userdict = self.get_single({"login": login}, "login",
 
369
            self.login_fields, self.login_primary,
353
370
            error_notfound="get_user: No user with that login name", dry=dry)
 
371
        if dry:
 
372
            return userdict     # Query string
 
373
        # Package into a User object
 
374
        return user.User(**userdict)
354
375
 
355
376
    def get_users(self, dry=False):
356
 
        """Returns a list of all users. The list elements are a dictionary of
357
 
        the user's DB fields, excluding the passhash field.
 
377
        """Returns a list of all users in the DB, as User objects.
358
378
        """
359
 
        return self.get_all("login", self.login_getfields, dry=dry)
 
379
        userdicts = self.get_all("login", self.login_fields, dry=dry)
 
380
        if dry:
 
381
            return userdicts    # Query string
 
382
        # Package into User objects
 
383
        return [user.User(**userdict) for userdict in userdicts]
360
384
 
361
385
    def user_authenticate(self, login, password, dry=False):
362
386
        """Performs a password authentication on a user. Returns True if
363
387
        "passhash" is the correct passhash for the given login, False
364
 
        otherwise.
 
388
        if the passhash does not match the password in the DB,
 
389
        and None if the passhash in the DB is NULL.
365
390
        Also returns False if the login does not exist (so if you want to
366
391
        differentiate these cases, use get_user and catch an exception).
367
392
        """
368
 
        query = ("SELECT login FROM login "
369
 
            "WHERE login = '%s' AND passhash = %s;"
370
 
            % (login, _escape(_passhash(password))))
 
393
        query = "SELECT passhash FROM login WHERE login = '%s';" % login
371
394
        if dry: return query
372
395
        result = self.db.query(query)
373
 
        # If one row was returned, succeed.
374
 
        # Otherwise, fail to authenticate.
375
 
        return result.ntuples() == 1
 
396
        if result.ntuples() == 1:
 
397
            # Valid username. Check password.
 
398
            passhash = result.getresult()[0][0]
 
399
            if passhash is None:
 
400
                return None
 
401
            return _passhash(password) == passhash
 
402
        else:
 
403
            return False
376
404
 
377
405
    def close(self):
378
406
        """Close the DB connection. Do not call any other functions after