Beispiel #1
0
def update_pickled_dict(path, changes):
    """Update pickled dictionary on disk with provided changes"""

    saved_dict = load(path)
    saved_dict.update(changes)
    dump(saved_dict, path)
    return saved_dict
Beispiel #2
0
def manage_pending_peers(configuration, client_id, action, change_list):
    """Helper to manage changes to pending peers list of client_id"""
    _logger = configuration.logger
    client_dir = client_id_dir(client_id)
    pending_peers_path = os.path.join(configuration.user_settings, client_dir,
                                      pending_peers_filename)
    try:
        pending_peers = load(pending_peers_path)
    except Exception as exc:
        if os.path.exists(pending_peers_path):
            _logger.warning("could not load pending peers from %s: %s" %
                            (pending_peers_path, exc))
        pending_peers = []
    change_dict = dict(change_list)
    # NOTE: always remove old first to replace any existing and move them last
    pending_peers = [(i, j)
                     for (i, j) in pending_peers if not i in change_dict]
    if action == "add":
        pending_peers += change_list
    elif action == "remove":
        pass
    else:
        _logger.error(
            "unsupported action in manage pending peers: %s" % action)
        return False
    try:
        dump(pending_peers, pending_peers_path)
        return True
    except Exception as exc:
        _logger.warning("could not save pending peers to %s: %s" %
                        (pending_peers_path, exc))
        return False
Beispiel #3
0
def pickle(data_object, path, logger):
    """Pack data_object as pickled object in path"""
    try:
        dump(data_object, path)
        logger.debug('pickle success: %s' % path)
        return True
    except Exception as err:
        logger.error('could not pickle: %s %s' % (path, err))
        return False
Beispiel #4
0
def filter_pickled_list(path, changes):
    """Filter pickled list on disk with provided changes where changes is a
    dictionary mapping existing list entries and the value to replace it with.
    """

    saved_list = load(path)
    saved_list = [changes.get(entry, entry) for entry in saved_list]
    dump(saved_list, path)
    return saved_list
Beispiel #5
0
def filter_pickled_dict(path, changes):
    """Filter pickled dictionary on disk with provided changes where changes
    is a dictionary mapping existing dictionary values to a value to replace
    it with.
    """

    saved_dict = load(path)
    for (key, val) in saved_dict.items():
        if val in changes.keys():
            saved_dict[key] = changes[val]
    dump(saved_dict, path)
    return saved_dict
Beispiel #6
0
def write_sitestats(configuration, stats, path_prefix, output_format):
    """Dump stats to file(s) of given output_format(s) using format name
    as extension"""

    for ext in output_format:
        dst_path = "%s.%s" % (path_prefix, ext)
        if ext == 'csv':
            out = format_csv(configuration, stats)
            with open(dst_path, "w") as fh:
                fh.write(out)
        elif ext == 'txt':
            out = format_txt(configuration, stats)
            with open(dst_path, "w") as fh:
                fh.write(out)
        elif ext in ['json', 'yaml', 'pickle']:
            dump(stats, dst_path, serializer=ext)
        else:
            return False
    return True
Beispiel #7
0
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False, op_menu=False)
    defaults = signature()[1]
    client_dir = client_id_dir(client_id)
    logger.debug('in peersaction: %s' % user_arguments_dict)
    (validate_status, accepted) = validate_input(user_arguments_dict,
                                                 defaults,
                                                 output_objects,
                                                 allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    if not safe_handler(configuration, 'post', op_name, client_id,
                        get_csrf_limit(configuration), accepted):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Only accepting
CSRF-filtered POST requests to prevent unintended updates'''
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Save Peers'
    output_objects.append({'object_type': 'header', 'text': 'Save Peers'})

    admin_email = configuration.admin_email
    smtp_server = configuration.smtp_server
    user_pending = os.path.abspath(configuration.user_pending)

    user_map = get_full_user_map(configuration)
    user_dict = user_map.get(client_id, None)
    # Optional site-wide limitation of peers permission
    if not user_dict or \
            not peers_permit_allowed(configuration, user_dict):
        logger.warning("user %s is not allowed to permit peers!" % client_id)
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Only privileged users can permit external peers!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    action = accepted['action'][-1].strip()
    label = accepted['peers_label'][-1].strip()
    kind = accepted['peers_kind'][-1].strip()
    raw_expire = accepted['peers_expire'][-1].strip()
    peers_content = accepted['peers_content']
    peers_format = accepted['peers_format'][-1].strip()
    peers_invite = accepted['peers_invite'][-1].strip()
    do_invite = (peers_invite.lower() in ['on', 'true', 'yes', '1'])

    try:
        expire = datetime.datetime.strptime(raw_expire, '%Y-%m-%d')
        if datetime.datetime.now() > expire:
            raise ValueError("specified expire value is in the past!")
    except Exception as exc:
        logger.error("expire %r could not be parsed into a (future) date" %
                     raw_expire)
        output_objects.append({
            'object_type':
            'text',
            'text':
            'No valid expire provided - using default: %d days' %
            default_expire_days
        })
        expire = datetime.datetime.now()
        expire += datetime.timedelta(days=default_expire_days)
    expire = expire.date().isoformat()

    if not action in peer_actions:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Unsupported peer action %r - only %s are allowed' %
            (action, ', '.join(peer_actions))
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
    if not kind in peer_kinds:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Unsupported peer kind %r - only %s are allowed' %
            (kind, ', '.join(peer_kinds))
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
    # TODO: implement and enable more formats?
    if peers_format not in ("csvform", 'userid'):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Only Import Peers is implemented so far!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    peers_path = os.path.join(configuration.user_settings, client_dir,
                              peers_filename)
    try:
        all_peers = load(peers_path)
    except Exception as exc:
        logger.warning("could not load peers from: %s" % exc)
        all_peers = {}

    # Extract peer(s) from request
    (peers, err) = parse_peers(configuration, peers_content, peers_format)
    if not err and not peers:
        err = ["No valid peers provided"]
    if err:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Parsing failed: %s' % '.\n '.join(err)
        })
        output_objects.append({
            'object_type': 'link',
            'destination': 'peers.py',
            'text': 'Back to peers'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # NOTE: general cases of operation here:
    # * import multiple peers in one go (add new, update existing)
    # * add one or more new peers
    # * update one or more existing peers
    # * remove one or more existing peers
    # * accept one or more pending requests
    # * reject one or more pending requests
    # The kind and expire values are generally applied for all included peers.

    # NOTE: we check all peers before any action
    for user in peers:
        fill_distinguished_name(user)
        peer_id = user['distinguished_name']
        cur_peer = all_peers.get(peer_id, {})
        if 'add' == action and cur_peer:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'Peer %r already exists!' % peer_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif 'update' == action and not cur_peer:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'Peer %r does not exists!' % peer_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif 'remove' == action and not cur_peer:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'Peer %r does not exists!' % peer_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif 'accept' == action and cur_peer:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'Peer %r already accepted!' % peer_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif 'reject' == action and cur_peer:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'Peer %r already accepted!' % peer_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif 'import' == action and cur_peer:
            # Only warn on import with existing match
            output_objects.append({
                'object_type': 'text',
                'text': 'Updating existing peer %r' % peer_id
            })

    # Now apply changes
    for user in peers:
        peer_id = user['distinguished_name']
        cur_peer = all_peers.get(peer_id, {})
        user.update({'label': label, 'kind': kind, 'expire': expire})
        if 'add' == action:
            all_peers[peer_id] = user
        elif 'update' == action:
            all_peers[peer_id] = user
        elif 'remove' == action:
            del all_peers[peer_id]
        elif 'accept' == action:
            all_peers[peer_id] = user
        elif 'reject' == action:
            pass
        elif 'import' == action:
            all_peers[peer_id] = user
        logger.info("%s peer %s" % (action, peer_id))

    try:
        dump(all_peers, peers_path)
        logger.debug('%s %s peers %s in %s' %
                     (client_id, action, all_peers, peers_path))
        output_objects.append({
            'object_type': 'text',
            'text': "Completed %s peers" % action
        })
        for user in peers:
            output_objects.append({
                'object_type': 'text',
                'text': "%(distinguished_name)s" % user
            })
        if action in ['import', 'add', 'update']:
            client_name = extract_field(client_id, 'full_name')
            client_email = extract_field(client_id, 'email')

            if do_invite:
                succeeded, failed = [], []
                email_header = '%s Invitation' % configuration.short_title
                email_msg_template = """Hi %%s,
This is an automatic email sent on behalf of %s who vouched for you to get a
user account on %s. You can accept the invitation by going to
%%s
entering a password of your choice and submitting the form.
If you do not want a user account you can safely ignore this email.

We would be grateful if you report any abuse of the invitation system to the
site administrators (%s).
""" % (client_name, configuration.short_title, admin_email)
                for peer_user in peers:
                    peer_name = peer_user['full_name']
                    peer_email = peer_user['email']
                    peer_url = os.path.join(
                        configuration.migserver_https_sid_url, 'cgi-sid',
                        'reqoid.py')
                    peer_req = {}
                    for field in peers_fields:
                        peer_req[field] = peer_user.get(field, '')
                    peer_req['comment'] = 'Invited by %s (%s) for %s purposes' \
                                          % (client_name, client_email, kind)
                    # Mark ID fields as readonly in the form to limit errors
                    peer_req['ro_fields'] = keyword_auto
                    peer_url += '?%s' % urllib.urlencode(peer_req)
                    email_msg = email_msg_template % (peer_name, peer_url)
                    logger.info(
                        'Sending invitation: to: %s, header: %s, msg: %s, smtp_server: %s'
                        % (peer_email, email_header, email_msg, smtp_server))
                    if send_email(peer_email, email_header, email_msg, logger,
                                  configuration):
                        succeeded.append(peer_email)
                    else:
                        failed.append(peer_email)

                if failed:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        """An error occured trying to email the peer
invitation to %s . Please inform the site admins (%s) if the problem persists.
""" % (', '.join(failed), admin_email)
                    })
                if succeeded:
                    output_objects.append({
                        'object_type':
                        'text',
                        'text':
                        """Sent invitation to %s with a link to a mostly pre-filled %s account request
form with the exact ID fields you provided here.""" %
                        (', '.join(succeeded), configuration.short_title)
                    })
            else:
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    """Please tell your peers
to request an account at %s with the exact ID fields you provided here and
importantly mentioning the purpose and your email (%s) in the sign up Comment
field. Alternatively you can use the invite button to send out an email with a
link to a mostly prefilled request form.""" %
                    (configuration.short_title, client_email)
                })
    except Exception as exc:
        logger.error('Failed to save %s peers to %s: %s' %
                     (client_id, peers_path, exc))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''
Could not %s peers %r. Please contact the site admins on %s if this error
persists.
''' % (action, label, admin_email)
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    if action in ["accept", "reject"]:
        changed = [(i['distinguished_name'], i) for i in peers]
        if not manage_pending_peers(configuration, client_id, "remove",
                                    changed):
            logger.warning('could not update pending peers for %s after %s' %
                           (client_id, action))

    logger.info('%s completed for %s peers for %s in %s' %
                (action, label, client_id, peers_path))

    user_lines = []
    pretty_peers = {'label': label, 'kind': kind, 'expire': expire}
    for user in peers:
        user_lines.append(user['distinguished_name'])
    pretty_peers['user_lines'] = '\n'.join(user_lines)
    email_header = '%s Peers %s' % (configuration.short_title, action)
    email_msg = """Received %s peers from %s
""" % (action, client_id)
    email_msg += """
Kind: %(kind)s , Expire: %(expire)s, Label: %(label)s , Peers:
%(user_lines)s
""" % pretty_peers

    logger.info('Sending email: to: %s, header: %s, msg: %s, smtp_server: %s' %
                (admin_email, email_header, email_msg, smtp_server))
    if not send_email(admin_email, email_header, email_msg, logger,
                      configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''
An error occured trying to send the email about your %s peers to the site
administrators. Please manually inform them (%s) if the problem persists.
''' % (action, admin_email)
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append({
        'object_type':
        'text',
        'text':
        '''
Informed the site admins about your %s peers action to let them accept peer
account requests you already validated.''' % action
    })

    output_objects.append({
        'object_type': 'link',
        'destination': 'peers.py',
        'text': 'Back to peers'
    })
    return (output_objects, returnvalues.OK)
Beispiel #8
0
from mig.shared.conf import get_configuration_object

configuration = get_configuration_object()

sandboxdb_file = configuration.sandbox_home + os.sep\
     + 'sandbox_users.pkl'

PW = 0
RESOURCES = 1

try:
    username = sys.argv[1]
except:
    print('You must specify a username.')
    sys.exit(1)

# Load the user file

userdb = load(sandboxdb_file)

if username in userdb:

    # Open the user file in write-mode - this deletes the file!

    del userdb[username]
    dump(userdb, sandboxdb_file)
    print('Username %s has now been deleted!' % username)
else:
    print('Sorry, username does not exist: %s' % username)
    sys.exit(0)