fedora-accounts website.py,NONE,1.1

Elliot Lee (sopwith) fedora-extras-commits at redhat.com
Thu Jun 15 23:14:14 UTC 2006


Author: sopwith

Update of /cvs/fedora/fedora-accounts
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv18227

Added Files:
	website.py 
Log Message:
addme - minus passwords in history


--- NEW FILE website.py ---
import pgdb
if not hasattr(pgdb, 'INV_READ'):
    pgdb.INV_READ = pgdb._pg.INV_READ
if not hasattr(pgdb, 'INV_WRITE'):
    pgdb.INV_WRITE = pgdb._pg.INV_WRITE
pgdb.pgdbCnx.getlo = lambda self, lo_oid: self._pgdbCnx__cnx.getlo(lo_oid)
pgdb.pgdbCnx.locreate = lambda self, mode: self._pgdbCnx__cnx.locreate(mode)
pgdb.pgdbCnx.loimport = lambda self, filename: self._pgdbCnx__cnx.loimport(filename)
import sys
import Cookie
import os, string
import socket
import base64

rows_per_page = 25
domain = 'fedoraproject.org'
accounts_email = 'accounts@%s' % domain
legal_cla_email = 'legal-cla-archive at fedora.redhat.com'
accounts_url = 'https://admin.fedoraproject.org/accounts/'
dbname_map = {'auth':'fedorausers'}
dbctx_map = {'auth':'live', 'metrics':'metrics-source'}
dbcnx_map = {}

fh = aline = pieces = None
if os.environ.has_key('HOME') and os.path.isfile(os.environ.get('HOME') + '/.fedora-db-access'):
    fh = open(os.environ.get('HOME') + '/.fedora-db-access', 'r')
elif os.path.isfile('/etc/sysconfig/fedora-db-access'):
    fh = open('/etc/sysconfig/fedora-db-access', 'r')
while fh:
    aline = fh.readline()
    if not aline: break
    aline = aline.strip()
    if not aline or aline[0] == '#': continue
    pieces = aline.split(None, 1)
    if len(pieces) < 2: continue
    dbcnx_map[pieces[0]] = eval(pieces[1])
if fh: fh.close()
del fh, aline, pieces

role_type_names = ['user', 'sponsor', 'administrator']

def print_header(title, auth_username=None, cache=0):
    print "Content-type: text/html"
    if not cache and 0:
        print "Cache-Control: no-cache, must-revalidate, no-store"
    sys.stdout.write('\n')
    window_title = title
    if auth_username:
        window_title += ' - Logged in as ' + auth_username
    pieces = {'pagetitle':window_title,'accountsurl':accounts_url}
    print """

<html>
	<head>
	<title>%(pagetitle)s</title>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<style type="text/css" media="screen">
			@import url("http://fedora.redhat.com/css/layout.css");
			@import url("http://fedora.redhat.com/css/content.css");
			@import url("http://fedora.redhat.com/css/docbook.css");
		</style>
		<meta name="MSSmartTagsPreventParsing" content="TRUE">
	</head>
	<body>
		<!-- header BEGIN -->
		<div id="fedora-header">
			<div id="fedora-header-logo">
				<a href="/"><img src="http://fedora.redhat.com/images/header-fedora_logo.png" alt="Fedora Project"></a>
			</div>

			<div id="fedora-header-items">
				<span class="fedora-header-icon">
				
				<!-- 	<a href="/download/"><img src="images/header-download.png" alt="">Download</a>
					<a href="/projects/"><img src="images/header-projects.png" alt="">Projects</a>
					<a href="/about/faq/"><img src="images/header-faq.png" alt="">FAQ</a></span> -->
			</div>
		</div>

		<div id="fedora-nav"></div>
		<!-- header END -->
		
		<!-- leftside BEGIN -->
		<div id="fedora-side-left">
		<div id="fedora-side-nav-label">Site Navigation:</div>
			<ul id="fedora-side-nav">
				<li><strong><a href="%(accountsurl)s">Accounts Home</a></strong></li>
				<li><a href="http://fedoraproject.org/wiki/Infrastructure/AccountSystem">Help</a></li>
			</ul>
		</div>

		<!-- leftside END -->

		<!-- content BEGIN -->
		<div id="fedora-middle-three">
			<div class="fedora-corner-tr"> </div>
			<div class="fedora-corner-tl"> </div>
			<div id="fedora-content">
		
<div id="page-main">

""" % pieces

def print_footer(title, return_to=None):
    if return_to:
        print '<a href="%s">Return</a>' % return_to
    pieces = {'pagetitle':title}
    print """
</div>
		</div>
			<div class="fedora-corner-br"> </div>
			<div class="fedora-corner-bl"> </div>
		</div>
		<!-- content END -->
		<!-- rightside BEGIN --><div id="fedora-side-right"><div class="fedora-side-right-content">
<h1>Links</h1>
<p>Links to other sites	<ul>
				<li><a href="http://fedora.redhat.com">Fedora Home</a></li>
<li><a href="http://fedoranews.org">Fedora News</a></li>
<li><a href="http://fedoralegacy.org/">Fedora Legacy Project</a></li>
<li><a href="http://fedoraproject.org">Fedora Project</a></li></ul></p>
</div>
</div><!-- rightside END -->
		<!-- footer BEGIN -->
		<div id="fedora-footer">
			Copyright © 2003-2006 Red Hat, Inc. All rights reserved.
			<br>Fedora is a trademark of Red Hat, Inc. 
			<br>The Fedora Project is not a supported product of Red Hat, Inc.
			<br>Red Hat, Inc. is not responsible for the content of other sites. 
			<br><a href="http://fedora.redhat.com/About/legal/">Legal</a> | <a
href="http://fedora.redhat.com/About/legal/trademarks/">Trademark Guidelines</a>
			<br>
		</div>
		<!-- footer END -->
	</body>
</html>
""" % pieces

class PostgresDBCursor:
    def __init__(self, dbc):
        self.dbc = dbc

    def __getattr__(self, key):
        return getattr(self.dbc, key)

    def fetchhash(self):
        dbr = self.dbc.fetchone()
        if not dbr:
            return None
        dbd = {}
        oldval = None
        descr = self.dbc.description
        for I in range(0, len(dbr)):
            dbd[descr[I][0]] = dbr[I]
        return dbd

class PostgresDBConnection:
    def __init__(self, *args, **kw):
        self.dbh = apply(pgdb.connect, args, kw)

    def __getattr__(self, key):
        return getattr(self.dbh, key)

    def cursor(self):
        return PostgresDBCursor(self.dbh.cursor())

def get_dbh(dbtype='auth', dbctx=None):
    dbname = dbname_map.get(dbtype, dbtype)
    if dbctx is None:
	hn = socket.gethostname()
	if hn.find('devel.redhat.com') >= 0:
		dbctx = 'devel'
	else:
		dbctx = dbctx_map.get(dbname, 'live')
    dbcnx = dbcnx_map[dbctx]
    dbhost = dbcnx['host']
    dbuser = dbcnx['user']
    dbpass = dbcnx.get('password')
    return PostgresDBConnection(database=dbname, host=dbhost, user=dbuser, password=dbpass)

def do_checkpass(dbh, username, password):
    x = do_checkpass_full(dbh, username, password)
    if x is not None:
        return x['username']

def do_checkpass_full(dbh, username, password):
    if not username or not password:
        return
    dbc = dbh.cursor()
    dbc.execute("SELECT * FROM person WHERE username = %s OR email = %s", (username.lower(), username))
    arow = dbc.fetchhash()
    if not arow or arow['password'] != password:
        return
    return arow

def set_auth(username='', password=''):
    c = Cookie.SmartCookie()
    c.load(os.environ.get('HTTP_COOKIE', ''))
    if c.has_key('auth_username'):
        c['auth_username'] = username
    if c.has_key('auth_password'):
        c['auth_password'] = password
    if c:
        print c
    return c

clear_auth = set_auth

def get_auth(dbh, form):
    c = Cookie.SimpleCookie()
    c.load(os.environ.get('HTTP_COOKIE', ''))
    username = None
    if form.has_key('username'):
        username = form['username'].value
    auth_username = username
    if form.has_key('auth_username'):
        auth_username = form['auth_username'].value
    elif c.has_key('auth_username'):
        auth_username = c['auth_username'].value
    auth_password = None
    if form.has_key('auth_password'):
        auth_password = form['auth_password'].value
    elif c.has_key('auth_password'):
        auth_password = c['auth_password'].value
    if dbh is None:
        dbh = get_dbh()
    x = do_checkpass(dbh, auth_username, auth_password)
    if not x:
        auth_username = auth_password = None
    else:
	auth_username = x
    if not (auth_username or not auth_password):
        if c.has_key('auth_username'):
            del c['auth_username']
        if c.has_key('auth_password'):
            del c['auth_password']
    else:
        c['auth_username'] = auth_username
        c['auth_password'] = auth_password
    print c
    return auth_username, auth_password

def get_user_info(dbh, userkey):
    dbc = dbh.cursor()
    if isinstance(userkey, str):
        dbc.execute("SELECT * FROM person WHERE username = %s OR email = %s", (userkey, userkey))
    else:
        dbc.execute("SELECT * FROM person WHERE id = %s", (userkey,))
    return dbc.fetchhash()

def get_user_id(dbh, username):
    dbc = dbh.cursor()
    dbc.execute("SELECT id FROM person WHERE username = %s OR email = %s", (username, username))
    arow = dbc.fetchone()
    if arow: return arow[0]

def get_user_name(dbh, user_id):
    dbc = dbh.cursor()
    dbc.execute("SELECT username FROM person WHERE id = %s", (user_id,))
    arow = dbc.fetchone()
    if arow: return arow[0]

def get_group_id(dbh, groupname):
    dbc = dbh.cursor()
    dbc.execute("SELECT id FROM project_group WHERE name = %s", (groupname, ))
    arow = dbc.fetchone()
    if arow: return arow[0]

def get_group_name(dbh, group_id):
    dbc = dbh.cursor()
    dbc.execute("SELECT name FROM project_group WHERE id = %s", (group_id,))
    arow = dbc.fetchone()
    if arow: return arow[0]

def get_group_info(dbh, groupkey):
    dbc = dbh.cursor()
    if isinstance(groupkey, str):
        dbc.execute("SELECT * FROM project_group WHERE name = %s", (groupkey,))
    else:
        dbc.execute("SELECT * FROM project_group WHERE id = %s", (groupkey,))
    return dbc.fetchhash()

def get_user_groups(dbh, userid, role_status=('approved',)):
    dbc = dbh.cursor()
    dbc.execute("SELECT project_group.id, project_group.name, role.role_type, role.role_status FROM role, project_group, person WHERE role.person_id = person.id AND role.project_group_id = project_group.id AND person.id = %s AND (project_group.needs_sponsor = 0 OR role.sponsor_id IS NOT NULL) AND role.role_status IN %s AND person.approval_status = 'approved'", (userid, role_status))
    retval = []
    while 1:
        arow = dbc.fetchone()
        if not arow: break
        retval.append(arow)
    return retval
    
    

def send_email(fromaddr, to, subject, body, cc=None):
    import email.Message, popen2
    msg = email.Message.Message()
    if not isinstance(to, tuple) and not isinstance(to, list):
        to = [to]
    msg.add_header('To', ', '.join(to))
    if cc:
        if not isinstance(cc, tuple) and not isinstance(cc, list):
            cc = [cc]
        msg.add_header('Cc', ', '.join(cc))
    msg.add_header('From', fromaddr)
    msg.add_header('Subject', subject)
    msg.set_payload(body)
    fh_read, fh_write = popen2.popen2("/usr/sbin/sendmail -t")
    fh_read.close()
    fh_write.write(str(msg))
    fh_write.close()

def do_error(title, message=None):
    if message:
        print "<hr>" + message
    print_footer(title)
    sys.exit(0)

def handle_auth(auth_username, auth_password, form, url, title=None, require_auth=1):
    if auth_username: auth_username = auth_username.lower()
    if not (auth_username and auth_password) and require_auth:
        if not auth_username: auth_username = ''
        if form.has_key('auth_password'):
            print 'Username or password not valid. <a href="%s/reset-password.cgi?username=%s">Reset password</a><br>' % (accounts_url, auth_username)
        print """<form method=post action="%s">Username: <input type=text name=auth_username value="%s"><br>Password: <input type=password name=auth_password><br><input type=submit value=Login>""" % (url, auth_username)
	for I in form.keys():
		if I in ('auth_username', 'auth_password'): continue
		print '<input type=hidden name="%s" value="%s">' % (I, form[I].value)
	print "</form>"
        do_error(title)
    return auth_username, auth_password

def have_group(dbh, username, group=None, require_role_type=None, require_role_domain=None, group_info=None):
    if username in ('admin',): return 'administrator'
    dbc = dbh.cursor()
    qry = "SELECT role.role_type, project_group.needs_sponsor, project_group.user_can_remove, project_group.name, project_group.prerequisite_id FROM role, project_group, person WHERE role.person_id = person.id AND "
    qspecs = ["project_group.id = role.project_group_id", "role.role_status = 'approved'"]
    qspecs_base = []
    qargs = []
    if group:
        if isinstance(group, str):
            qgrp = "project_group.name = %s"
        else:
            qgrp = "project_group.id = %s"
        qspecs_base.append(qgrp)
        qargs.append(group)
    if isinstance(username, str):
        quser = "person.username = %s"
    else:
        quser = "person.id = %s"
    qspecs_base.append(quser)
    qargs.append(username)
    qry += ' AND '.join(qspecs_base + qspecs)
    dbc.execute("SELECT project_group.owner_id, person.id FROM project_group, person WHERE " + ' AND '.join(qspecs_base + ['project_group.owner_id = person.id']), qargs)
    arow = dbc.fetchone()
    default_retval = None
    if arow: # Group owner
        default_retval = 'administrator'
    if require_role_type:
	if isinstance(require_role_type, tuple) or isinstance(require_role_type, list):
	    qry += ' AND role.role_type IN %s'
	else:
            require_role_type = role_type_names[role_type_names.index(require_role_type):]
	    qry += ' AND role.role_type IN %s'
        qargs.append(require_role_type)
    if require_role_domain:
        qry += " AND (role.role_domain + '%%') LIKE %s"
        qargs.append(require_role_domain)
    dbc.execute(qry, qargs)
    if dbc.rowcount > 0:
        arow = dbc.fetchhash()
        if group_info: group_info.update(arow)
        return arow['role_type']
    return default_retval

def get_allowed_group_actions(dbh, auth_username, groupname, group_info=None, for_username=None):
    allowed_actions = []
    if have_group(dbh, auth_username, 'accounts'):
        allowed_actions.extend(['remove', 'approve', 'decline', 'sponsor', 'admin', 'upgrade', 'downgrade'])
    my_group_info = {}
    if group_info is not None:
        my_group_info = group_info
    ginfo = get_group_info(dbh, groupname)
    my_group_info.update(ginfo)
    if my_group_info['name'] == 'cla_done':
	return []
    x = have_group(dbh, auth_username, groupname, group_info=my_group_info)
    if x:
	allowed_actions.append(x)
	allowed_actions.append('member')
        if my_group_info.get('user_can_remove', 1):
            allowed_actions.extend(['remove_self'])
        if x in ('sponsor', 'administrator') and my_group_info.get('needs_sponsor'):
            allowed_actions.extend(['sponsor'])
        if x in ('administrator', 'sponsor'):
            allowed_actions.extend(['decline', 'remove'])
	    if not my_group_info.get('needs_sponsor'):
                allowed_actions.extend(['approve'])
        if x == 'administrator':
            allowed_actions.extend(['upgrade', 'downgrade'])
    if my_group_info and (not my_group_info['prerequisite_id'] or have_group(dbh, auth_username, my_group_info['prerequisite_id'])):
        allowed_actions.append('add_self')
    if for_username and my_group_info and (not my_group_info['prerequisite_id'] or have_group(dbh, for_username, my_group_info['prerequisite_id'])):
        allowed_actions.append('add')
    return allowed_actions

def handle_group_mods(dbh, form, url, username, groupname, fixed_item=None, auth_username=None):
    # Handle actions
    dbc = dbh.cursor()
    if not auth_username:
        auth_username = username
    permitted = 0
    if form.has_key('_role_add'):
      group_info = {}
      role_group = form['groupname'].value
      role_user = form['username'].value
      allowed_actions = get_allowed_group_actions(dbh, auth_username, role_group, group_info=group_info, for_username=role_user)
      if role_user == auth_username:
            permitted = 'add_self' in allowed_actions
      else:
            permitted = 'add' in allowed_actions
      if group_info and permitted:
        # Add role
        role_domain = ''
        if form.has_key('role_domain'): role_domain = form['role_domain'].value
        role_status = 'unapproved'

        dbc.execute("SELECT id FROM project_group WHERE name = %s", (role_group,))
        arow = dbc.fetchone()
        assert arow, role_group
        role_group_id = arow[0]
        dbc.execute("SELECT id FROM person WHERE username = %s OR email = %s", (role_user, role_user))
        arow = dbc.fetchone()
        assert arow, role_user
        role_user_id = arow[0]
        dbc.execute("INSERT INTO role (person_id, project_group_id, role_domain, role_type, role_status) VALUES (%s, %s, %s, %s, %s)",
                    (role_user_id, role_group_id, role_domain, form['role_type'].value, role_status))
        dbh.commit()
        group_info.update(get_user_info(dbh, role_user_id))
        if group_info['needs_sponsor']:
            send_email(accounts_email, "%s-sponsors@%s" % (role_group, domain),
                       "Fedora %s sponsor needed for %s" % (role_group, role_user),
                       """

Fedora user %(username)s, aka %(human_name)s <%(email)s> has requested
membership in the %(name)s group and needs a sponsor.

Please go to https://admin.fedora.redhat.com/accounts/groupbox.cgi?_editme=Edit&name=%(name)s to take action.

-- The Fedora Account System
""" % group_info,
                       cc=group_info['email'])
        else:
            send_email(accounts_email, "%s-sponsors@%s" % (role_group, domain),
                       "Fedora %s membership approval needed for %s" % (role_group, role_user),
                       """

Fedora user %(username)s, aka %(human_name)s <%(email)s> has requested
membership in the %(name)s group - that membership needs approval.

Please go to https://admin.fedora.redhat.com/accounts/groupbox.cgi?_editme=Edit&name=%(name)s to take action.

-- The Fedora Account System
""" % group_info,
                       cc=group_info['email'])
      else:
        print "'Add' action denied."
	if not group_info:
	    print " The %s group doesn't seem to exist." % (role_group,)
        elif group_info['prerequisite_id']:
            print " You may need to become a member of the %s group first." % (get_group_info(dbh, group_info['prerequisite_id'])['name'])
        
    if form.has_key('_role_remove'):
        auth_user_id = get_user_id(dbh, auth_username)
        # Remove role(s)
        assert form.has_key('existing_roles')
        x = form['existing_roles']
        if not isinstance(x, list):
            x = [x]
        for I in x:
            role_group, role_user, role_domain = I.value.split('!', 2)
            role_group_id = get_group_id(dbh, role_group)
            assert role_group_id, role_group
            role_user_id = get_user_id(dbh, role_user)
            assert role_user_id, role_user

	    if role_domain == 'None': role_domain = None

            allowed_actions = get_allowed_group_actions(dbh, auth_username, role_group, for_username=role_user)
            if role_user_id == auth_user_id:
                permitted = 'remove' in allowed_actions or 'remove_self' in allowed_actions
            else:
                permitted = 'remove' in allowed_actions

            if permitted:
		if role_domain is None:
			rdc = "IS NULL"
			qargs = (role_user_id, role_group_id)
		else:
			rdc = " = %s"
			qargs = (role_user_id, role_group_id, role_domain)
                dbc.execute("DELETE FROM role WHERE person_id = %s AND project_group_id = %s AND role_domain " + rdc,
                            qargs)
            else:
                print "Removal of `%s' denied from group `%s'." % (role_user, role_group)
        dbh.commit()

    if form.has_key('_role_approve') or form.has_key('_role_decline'):
        if form.has_key('_role_approve'):
            new_status = 'approved'
            action_name = 'approve'
        if form.has_key('_role_decline'):
            new_status = 'declined'
            action_name = 'decline'

        auth_user_id = get_user_id(dbh, auth_username)
        # Remove role(s)
        assert form.has_key('existing_roles')
        x = form['existing_roles']
        if not isinstance(x, list):
            x = [x]
        for I in x:
            role_group, role_user, role_domain = inforow = I.value.split('!', 2)
            role_group_id = get_group_id(dbh, role_group)
            assert role_group_id, role_group
            role_user_id = get_user_id(dbh, role_user)
            assert role_user_id, role_user
            if role_domain == 'None':
                role_domain = None

            if role_domain is None:
                rolespec = "person_id = %s AND project_group_id = %s AND role_domain IS NULL"
                roleargs = (role_user_id, role_group_id)
            else:
                rolespec = "person_id = %s AND project_group_id = %s AND role_domain = %s"
                roleargs = (role_user_id, role_group_id, role_domain)
            allowed_actions = get_allowed_group_actions(dbh, auth_username, role_group, for_username=role_user)
            dbc.execute("SELECT sponsor_id, role_status FROM role WHERE " + rolespec, roleargs)
            arow = dbc.fetchone()
            if action_name == 'decline' and arow and arow[1] != 'unapproved':
                print "You cannot decline memberships that are already approved."
                continue
            elif action_name == 'approve' and arow and arow[1] == 'declined':
                print "You cannot decline memberships that are already approved."
                continue
            dbc.execute("SELECT needs_sponsor, prerequisite_id FROM project_group WHERE id = %s", (role_group_id,))
            needs_sponsor, prerequisite_id = dbc.fetchone()
            have_prereq = not prerequisite_id or have_group(dbh, role_user_id, prerequisite_id)
            if ((((arow and arow[0])
                 or not needs_sponsor)
                 and have_prereq)
                or action_name != 'approve') \
                and action_name in allowed_actions:
                if action_name == 'approve':
                    qry ="UPDATE role SET role_status = %s, approval = NOW() WHERE " + rolespec
                else:
                    qry ="UPDATE role SET role_status = %s WHERE " + rolespec
                if action_name == 'approve' and needs_sponsor:
                    qry += " AND sponsor_id IS NOT NULL"
                dbc.execute(qry,
                            (new_status, ) + roleargs)
                print "<p>Set status of %s to %s (%s)<p>" % (role_user, new_status, dbc.rowcount)
                uinfo = get_user_info(dbh, role_user_id)
                authi = get_user_info(dbh, auth_username)
                ginfo = get_group_info(dbh, role_group_id)
                joinmsg = ginfo.get('joinmsg', '')
                if action_name != 'approve':
                    joinmsg = ''
                send_email(accounts_email, uinfo['email'], "Your Fedora %s membership has been %s" % (role_group, new_status),
                           """

Membership in the %s group of the Fedora account system has been
%s by %s <%s> for your account %s. If applicable, this change should propogate into the e-mail
aliases and CVS repository within an hour.

%s
-- Fedora Account System
""" % (role_group, new_status, authi['human_name'], authi['email'], uinfo['username'], joinmsg),
                           cc=('%s-administrators@%s' % (role_group, domain)))
            elif action_name == 'approve':
                if needs_sponsor and arow and not arow[0]:
                    print "User `%s' in group `%s' does not yet have a sponsor." % (role_user, role_group)
                elif not have_prereq:
                    print "User `%s' in group `%s' does not yet belong to the prerequisite group, `%s'" \
                          % (role_user, role_group, get_group_name(dbh, prerequisite_id))
            else:
                print "Action denied on `%s' in group `%s'." % (role_user, role_group)
        dbh.commit()

    if form.has_key('_role_upgrade') or form.has_key('_role_downgrade'):
        auth_user_id = get_user_id(dbh, auth_username)
        # Remove role(s)
        if form.has_key('_role_upgrade'):
            the_action = 'upgrade'
            action_dir = 1
        else:
            the_action = 'downgrade'
            action_dir = -1
        assert form.has_key('existing_roles')
        x = form['existing_roles']
        if not isinstance(x, list):
            x = [x]
        for I in x:
            role_group, role_user, role_domain = I.value.split('!', 2)
            role_group_id = get_group_id(dbh, role_group)
            assert role_group_id, role_group
            role_user_id = get_user_id(dbh, role_user)
            assert role_user_id, role_user
            allowed_actions = get_allowed_group_actions(dbh, auth_username, role_group, for_username=role_user)
            dbc.execute("SELECT role.role_type, role.role_status FROM role, project_group WHERE person_id = %s AND project_group_id = %s AND role_domain = %s AND project_group_id = project_group.id",
                        (role_user_id, role_group_id, role_domain))
            arow = dbc.fetchone()
            try:
                type_num = role_type_names.index(arow[0])
            except:
                print "Action %s denied on `%s' in group `%s'<br/>" % (the_action, role_user, role_group)
                continue # Some funky role_type that we don't know about, or a non-existent role listing...
            if arow[1] != 'approved':
                print "Cannot %s `%s' in group `%s' until they are approved.<br/>" % (the_action, role_user, role_group)
                continue
            new_type_num = max(min(type_num + action_dir, len(role_type_names)-1), 0)
            if new_type_num == type_num:
                print "Cannot %s `%s' in group `%s' - they are already a %s.<br/>" % (the_action, role_user, role_group, role_type_names[new_type_num])
                continue
            new_type = role_type_names[new_type_num]
            if arow and the_action in allowed_actions:
		qry = "UPDATE role SET role_type = %s WHERE person_id = %s AND project_group_id = %s AND role_domain = %s"
		qargs = (new_type, role_user_id, role_group_id, role_domain)
                dbc.execute(qry, qargs)
                uinfo = get_user_info(dbh, role_user_id)
                authi = get_user_info(dbh, auth_user_id)
                ginfo = get_group_info(dbh, role_group_id)
                send_email(accounts_email, uinfo['email'], "Your Fedora %s membership has been %sd" % (role_group, the_action),
                           """

%s <%s> has %sd you to %s status in the %s group of the Fedora account
system. This change is effective immediately for new operations, and
should propogate into the e-mail aliases within an hour.

%s
-- Fedora Account System
""" % (authi['human_name'], authi['email'], the_action, new_type, role_group, ginfo.get('joinmsg', '')),
                           cc=('%s-administrators@%s' % (role_group, domain)))
            else:
                print "Action %s denied on `%s' in group `%s'.<br/>" % (the_action, role_user, role_group)
        dbh.commit()

    if form.has_key('_role_sponsor'):
        auth_user_id = get_user_id(dbh, auth_username)
        # Remove role(s)
        assert form.has_key('existing_roles')
        x = form['existing_roles']
        if not isinstance(x, list):
            x = [x]
        for I in x:
            role_group, role_user, role_domain = I.value.split('!', 2)
            role_group_id = get_group_id(dbh, role_group)
            assert role_group_id, role_group
            role_user_id = get_user_id(dbh, role_user)
            assert role_user_id, role_user

            allowed_actions = get_allowed_group_actions(dbh, auth_username, role_group, for_username=role_user)
            dbc.execute("SELECT role.sponsor_id, role.role_status, project_group.needs_sponsor FROM role, project_group WHERE person_id = %s AND project_group_id = %s AND role_domain = %s AND project_group_id = project_group.id",
                        (role_user_id, role_group_id, role_domain))
            arow = dbc.fetchone()
            if arow and not arow[0] and 'sponsor' in allowed_actions:
		if arow[2]:
			qstat = "role_status = %s, "
			qsa = ('approved',)
		else:
			qstat = ""
			qsa = ()
                        assert 0
		qry = "UPDATE role SET " + qstat + "sponsor_id = %s, approval = NOW() WHERE person_id = %s AND project_group_id = %s AND role_domain = %s AND sponsor_id IS NULL"
		qargs = qsa + (auth_user_id, role_user_id, role_group_id, role_domain)
                dbc.execute(qry, qargs)
                uinfo = get_user_info(dbh, role_user_id)
                authi = get_user_info(dbh, auth_user_id)
                ginfo = get_group_info(dbh, role_group_id)
                send_email(accounts_email, uinfo['email'], "Your Fedora %s membership has been sponsored" % (role_group, ),
                           """

%s <%s> has sponsored you for membership in the %s group of the Fedora
account system. If applicable, this change should propogate into the
e-mail aliases and CVS repository within an hour.

%s
-- Fedora Account System
""" % (authi['human_name'], authi['email'], role_group, ginfo.get('joinmsg', '')),
                           cc=('%s-administrators@%s' % (role_group, domain)))
            elif arow and arow[0]:
                print "User `%s' in group `%s' already has a sponsor." % (role_user, role_group)
            else:
                print "Action denied on `%s' in group `%s'." % (role_user, role_group)
        dbh.commit()
    print "<form method=post action=%s>" % url
    print "<hr noshade><table border width=100%><tr><td>"
    print "<h3>Add new membership</h3>"
    if fixed_item == 'username':
        print '<input type=hidden name=username value="%s">' % username
    else:
        print 'Username: <input type=text name=username maxlength=16><br>'
    if fixed_item == 'groupname':
        print '<input type=hidden name=groupname value="%s">' % groupname
        print '<input type=hidden name=name value="%s">' % groupname
    else:
        print 'Groupname: <input type=text name=groupname maxlength=16><br>'
    print 'Role type: <select name=role_type size=1>'
    for I in ('user', 'administrator', 'sponsor'):
        print '<option value="%s">%s</option>' % (I, I)
    print '</select><br>'
    print 'Role domain (normally empty): <input type=text name=role_domain maxlength=80><br>'
#    print 'Role status: <select name=role_status size=1>'
#    for I in ('unapproved', 'approved'):
#        print '<option value="%s">%s</option>' % (I, I)
    print '</select><br>'
    print '<input type=submit name=_role_add value="Add"></td>'
    qpc = "SELECT COUNT(role.*) FROM "
    qpr = "SELECT role.*, project_group.name, person.username, project_group.needs_sponsor, project_group.user_can_remove FROM "
    qtables = []
    qspecs = []
    qargs = []
    if fixed_item == 'groupname':
        qspecs.extend(['project_group.name = %s', 'project_group.id = role.project_group_id',
                       'person.id = role.person_id'])
        qtables.extend(['role', 'project_group', 'person'])
        qargs.append(groupname)
        order_by = 'person.username'
        default_role_show = 'unapproved'
    elif fixed_item == 'username':
        order_by = 'project_group.name'
        qtables.extend(['role', 'project_group', 'person'])
        qspecs.extend(["(person.username = %s OR person.email = %s)",
                       'project_group.id = role.project_group_id',
                       'person.id = role.person_id'])
        qargs.extend([username, username])
        default_role_show = 'all'
    else:
        assert 0, fixed_item
    role_show = default_role_show
    rsa_value = None
    rsu_value = None
    if form.has_key('_role_show_all'):
	rsa_value = form['_role_show_all'].value
    if form.has_key('_role_show_unapproved'):
	rsu_value = form['_role_show_unapproved'].value
    if rsa_value and rsa_value[:4].lower() == 'show':
        role_show = 'all'
    elif rsu_value and rsu_value[:4].lower() == 'show':
        role_show = 'unapproved'
    elif rsa_value:
	role_show = 'all'
    elif rsu_value:
	role_show = 'unapproved'
    if role_show == 'unapproved':
        qspecs.append("role_status = 'unapproved'")
    assert qtables
    dbc.execute('%s %s WHERE %s' % (qpc, ', '.join(qtables), ' AND '.join(qspecs)), qargs)
    rowcount = dbc.fetchone()[0]
    curpage = lastpage = 0
    if rowcount:
        lastpage = int((rowcount-1) / rows_per_page)
        if form.has_key('_role_cur_page'):
            curpage = int(form['_role_cur_page'].value)
        if form.has_key('_role_set_page_0'):
            curpage = 0
        if form.has_key('_role_set_page_last'):
            curpage = lastpage
        if form.has_key('_role_set_page_prev'):
            curpage -= 1
        if form.has_key('_role_set_page_next'):
            curpage += 1
        curpage = max(min(curpage, lastpage), 0)

        qry = '%s %s WHERE %s ORDER BY %s LIMIT %s OFFSET %s' \
              % (qpr,
                 ', '.join(qtables),
                 ' AND '.join(qspecs),
                 order_by,
                 rows_per_page,
                 curpage * rows_per_page)
        dbc.execute(qry, qargs)

    if 1 or (rowcount and dbc.rowcount):
        num_columns = 7

        print "<td valign=top><table><tr><td colspan=%s>" % num_columns
        print "<h3>Existing memberships</h3>"
        print '<input type=hidden name=_role_cur_page value=%s>' % curpage
        if lastpage:
            if curpage != 0:
                print '<input type=submit name=_role_set_page_0 value="|<"> '
                print '<input type=submit name=_role_set_page_prev value="<<"> '
            else:
                print "|< << "
            if curpage != lastpage:
                print '<input type=submit name=_role_set_page_next value=">>"> '
                print '<input type=submit name=_role_set_page_last value=">|"> '
            else:
                print ">> >|"
        for I in ('all', 'unapproved'):
            if role_show == I:
                print " <input type=hidden name=_role_show_%s value=1>Show %s" % (I, I)
            else:
                print ' <input type=submit name=_role_show_%s value="Show %s">' % (I, I)
        print "</td></tr><tr><th></th><th>Group Name</th><th>Username</th><th>Role Domain</th><th>Role Type</th><th>Role Status</th><th>Sponsor</th></tr>"

	if groupname:
		allowed_actions = get_allowed_group_actions(dbh, auth_username, groupname)
	else:
		allowed_actions = get_allowed_group_actions(dbh, auth_username, 'accounts') # XXX fixme badhack yuk
        got_needs_sponsor = 0
        got_needs_review = 0
        while 1:
            arow = dbc.fetchhash()
            if not arow: break
            print '<tr><td><input type=checkbox name=existing_roles value="%s!%s!%s"></td>' % (arow['name'],
                                                                                               arow['username'],
                                                                                               arow['role_domain'])
	    arow['print_role_status'] = arow['role_status']
	    if arow['print_role_status'] not in ('unapproved', 'approved', 'declined'):
		arow['print_role_status'] = 'In progress'
            for I in ('name', 'username', 'role_domain', 'role_type', 'print_role_status'):
                if I == 'username':
                    print """<td><a href="userbox.cgi?_editme=Edit&username=%s">%s</a></td>""" % (arow[I], arow[I])
                elif I == 'name':
                    print """<td><a href="groupbox.cgi?_editme=Edit&name=%s">%s</a></td>""" % (arow[I], arow[I])
                else:
                    print "<td>%s</td>" % arow[I]
            if arow['role_status'] != 'approved':
                got_needs_review = 1
            if arow['needs_sponsor']:
                if arow['role_status'] != 'approved' and arow['sponsor_id'] is None:
                    got_needs_sponsor = 1
                print "<td>%s</td>" % get_user_name(dbh, arow['sponsor_id'])
            else:
                print "<td><i>Unneeded</i></td>"
            print "</tr>"
            allowed_actions.extend(get_allowed_group_actions(dbh, auth_username, arow['name']))
        print "<tr><td colspan=%s>" % num_columns

        print "<p>"
        if (fixed_item == 'groupname' and 'remove' in allowed_actions) \
               or (fixed_item == 'username' and 'remove_self' in allowed_actions):
            print '<input type=submit name=_role_remove value="Remove Selected">'

        if 'sponsor' in allowed_actions and got_needs_sponsor:
            print '<input type=submit name=_role_sponsor value="Sponsor Selected">'
#	else:
#	    print " got_needs_sponsor %s, actions %s " % (got_needs_sponsor, allowed_actions)
        if 'approve' in allowed_actions and got_needs_review:
            print '<input type=submit name=_role_approve value="Approve Selected">'
        if 'decline' in allowed_actions and got_needs_review:
            print '<input type=submit name=_role_decline value="Decline Selected">'
        print '<input type=submit name=_role_upgrade value="Upgrade Selected">'
        print '<input type=submit name=_role_upgrade value="Downgrade Selected">'
#        print '<input type=submit name=_role_redisplay value="Redisplay list"></td></tr>'
        if lastpage:
            if curpage != 0:
                print '<input type=submit name=_role_set_page_0 value="|<"> '
                print '<input type=submit name=_role_set_page_prev value="<<"> '
            else:
                print "|< << "
            if curpage != lastpage:
                print '<input type=submit name=_role_set_page_next value=">>"> '
                print '<input type=submit name=_role_set_page_last value=">|"> '
            else:
                print ">> >|"
        print '</table>'
    print "</tr></table></form>"

def get_http_auth_info():
    http_cgi_auth = os.environ.get('HTTP_CGI_AUTHORIZATION')
    if not http_cgi_auth: return None, None
    authtype, authb64 = http_cgi_auth.split(None, 1)
    authinfo = base64.b64decode(authb64)
    if authtype.lower() == 'basic':
        authinfo = authinfo.split(':', 1)
    return authtype, authinfo

def get_rand_str(length=16, prand=0):
    if prand:
        fd = open("/dev/urandom", "r")
    else:
        fd = open("/dev/random", "r")
    h = string.hexdigits
    r = ''
    for c in fd.read(length/2):
        i = ord(c)
        r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
    fd.close()
    return r




More information about the fedora-extras-commits mailing list