Exemple #1
0
    def remove_user(self, username, pkg_name, collctn_list=None,
            collectn_list=None):
        '''Remove user from a package

        :arg username: Name of user to remove from the package
        :arg pkg_name: Name of the package
        :kwarg collctn_list: list of collection simple names like
            'F-10','devel'.  Default: None which means user removed from all
            collections associated with the package.
        :kwarg collectn_list: *Deprecated* Use collctn_list instead.
        :returns: status code from the request

        .. versionadded:: 0.3.12

        .. versionchanged:: 0.3.17
            Rename collectn_list to collctn_list
        '''
        if (collctn_list and collectn_list):
            warnings.warn(_('collectn_list is a deprecated name for'
                    ' collctn_list.\nIgnoring the value of collectn_list.'),
                    DeprecationWarning, stacklevel=2)

        if collectn_list and not collctn_list:
            warnings.warn(_('collectn_list has been renamed to collctn_list.\n'
                    'Please start using the new name.  collectn_list will go'
                    ' away in 0.4.x.'), DeprecationWarning, stacklevel=2)
            collctn_list = collectn_list

        if collctn_list:
            params = {'username': username, 'pkg_name': pkg_name, 
                'collectn_list': collctn_list}
        else:
            params = {'username': username, 'pkg_name': pkg_name}
        return self.send_request('/acls/dispatcher/remove_user', auth=True,
                   req_params=params)
Exemple #2
0
 def _clean_environ(self, environ):
     ''' Delete the ``keys`` from the supplied ``environ`` '''
     log.debug(_('clean_environ(%s)') % self.clear_env)
     for key in self.clear_env:
         if key in environ:
             log.debug(_('Deleting %(key)s from environ') % {'key': key})
             del(environ[key])
Exemple #3
0
    def print_recent_changes(self, days=7, show=10):
        now = datetime.utcnow()
        then = now - timedelta(days=days)
        print _(u"From %(then)s to %(now)s") % {'then': then, 'now': now}
        changes = self.get_recent_changes(now=now, then=then)
        num_changes = len(changes)
        print _(u"%d wiki changes in the past week") % num_changes
        if num_changes == 500:
            print _(
                u"""Warning: Number of changes reaches the API return limit.
You will not get the complete list of changes unless
you run this script using a 'bot' account.""")

        users = {}
        pages = {}
        for change in changes:
            users.setdefault(change['user'], []).append(change['title'])
            pages[change['title']] = pages.setdefault(change['title'], 0) + 1

        print _(u'\n== Most active wiki users ==')
        for user, changes in sorted(users.items(),
                                    cmp=lambda x, y: cmp(len(x[1]), len(y[1])),
                                    reverse=True)[:show]:
            print u' %-50s %d' % (('%s' % user).ljust(50, '.'),
                                  len(changes))

        print _(u'\n== Most edited pages ==')
        for page, num in sorted(pages.items(),
                                cmp=lambda x, y: cmp(x[1], y[1]),
                                reverse=True)[:show]:
            print u' %-50s %d' % (('%s' % page).ljust(50, '.'), num)
Exemple #4
0
    def add_metadata(self, environ, identity):
        log.info(_('In add_metadata'))
        req = webob.Request(environ)

        if identity.get('error'):
            log.info(_('Error exists in session, no need to set metadata'))
            return 'error'

        cookie = req.cookies.get(self.session_cookie)

        if cookie is None:
            # @@ Should we resort to this?
            #cookie = environ.get('CSRF_AUTH_SESSION_ID')
            return None

        log.info(_('Request metadata for cookie %(cookie)s') %
                {'cookie':cookie})
        info = fas_cache.get_value(key=cookie + '_metadata',
                createfunc=lambda: self.get_metadata(environ),
                expiretime=FAS_CACHE_TIMEOUT)

        identity.update(info)

        if 'repoze.what.credentials' not in environ:
            environ['repoze.what.credentials'] = {}

        environ['repoze.what.credentials']['groups'] = info['groups']
        environ['repoze.what.credentials']['permissions'] = info['permissions']

        # Adding the userid:
        userid = identity['repoze.who.userid']
        environ['repoze.what.credentials']['repoze.what.userid'] = userid
Exemple #5
0
    def identify(self, environ):
        log.info(_('in identify()'))
        req = webob.Request(environ)
        cookie = req.cookies.get(self.session_cookie)

        if cookie is None:
            return None

        log.info(_('Request identify for cookie %(cookie)s') %
                {'cookie': cookie})
        linfo = fas_cache.get_value(key=cookie + '_identity',
                                    createfunc=lambda: self.keep_alive(cookie),
                                    expiretime=FAS_CACHE_TIMEOUT)

        if not linfo:
            self.forget(environ, None)
            return None

        if not isinstance(linfo, tuple):
            return None

        try:
            me = linfo[1]
            me.update({'repoze.who.userid': me['username']})
            environ['FAS_LOGIN_INFO'] = linfo
            return me
        except Exception, e: # pylint:disable-msg=W0703
            # For any exceptions, returning None means we failed to identify
            log.warning(e)
            return None
Exemple #6
0
    def print_recent_changes(self, days=7, show=10):
        now = datetime.utcnow()
        then = now - timedelta(days=days)
        print _(u"From %(then)s to %(now)s") % {'then': then, 'now': now}
        changes = self.get_recent_changes(now=now, then=then)
        num_changes = len(changes)
        print _(u"%d wiki changes in the past week") % num_changes
        if num_changes == 500:
            print _(
                u"""Warning: Number of changes reaches the API return limit.
You will not get the complete list of changes unless
you run this script using a 'bot' account.""")

        users = {}
        pages = {}
        for change in changes:
            users.setdefault(change['user'], []).append(change['title'])
            pages[change['title']] = pages.setdefault(change['title'], 0) + 1

        print _(u'\n== Most active wiki users ==')
        for user, changes in sorted(users.items(),
                                    cmp=lambda x, y: cmp(len(x[1]), len(y[1])),
                                    reverse=True)[:show]:
            print u' %-50s %d' % (('%s' % user).ljust(50, '.'), len(changes))

        print _(u'\n== Most edited pages ==')
        for page, num in sorted(pages.items(),
                                cmp=lambda x, y: cmp(x[1], y[1]),
                                reverse=True)[:show]:
            print u' %-50s %d' % (('%s' % page).ljust(50, '.'), num)
Exemple #7
0
    def add_package(self, pkg, owner=None, description=None,
            branches=None, cc_list=None, comaintainers=None, groups=None):
        '''Add a package to the database.

        :arg pkg: Name of the package to edit
        :kwarg owner: If set, make this person the owner of both branches
        :kwarg description: If set, make this the description of both branches
        :kwarg branches: List of branches to operate on
        :kwarg cc_list: If set, list or tuple of usernames to watch the
            package.
        :kwarg comaintainers: If set, list or tuple of usernames to comaintain
            the package.
        :kwarg groups: If set, list or tuple of group names that can commit to
            the package.
        :raises AppError: If the server returns an error

        .. versionadded:: 0.3.13
        '''
        # See if we have the information to
        # create it
        if not owner:
            raise AppError(name='AppError', message=_('We do not have '
                    'enough information to create package %(pkg)s. '
                    'Need version owner.') % {'pkg': pkg})

        data = {'owner': owner, 'summary': description}
        # This call creates the package and an initial branch for
        # Fedora devel
        response = self.send_request('/acls/dispatcher/add_package/%s'
            % pkg, auth=True, req_params=data)
        if 'status' in response and not response['status']:
            raise AppError(name='PackageDBError', message=
                _('PackageDB returned an error creating %(pkg)s:'
                ' %(msg)s') % {'pkg': pkg, 'msg': response['message']})
            
        if cc_list:
            data['ccList'] = simplejson.dumps(cc_list)
        if comaintainers:
            data['comaintList'] = simplejson.dumps(comaintainers)

        # Parse the groups information
        if groups:
            data['groups'] = simplejson.dumps(groups)

        # Parse the Branch abbreviations into collections
        if branches:
            data['collections'] = []
            data['collections'] = branches
        del data['owner']

        if cc_list or comaintainers or groups or branches:
            response = self.send_request('/acls/dispatcher/'
                    'edit_package/%s' % pkg, auth=True, req_params=data)
            if 'status' in response and not response['status']:
                raise AppError(name='PackageDBError', 
                    message=_('Unable to save all information for'
                        ' %(pkg)s: %(msg)s') % {'pkg': pkg,
                        'msg': response['message']})
Exemple #8
0
def to_bytes(obj, encoding='utf8', errors='replace', non_string='empty'):
    '''Convert an object into a byte string

    Usually, this should be used on a unicode string but it can take byte
    strigs and unicode strings intelligently.  non_string objects are handled
    in different ways depending on the setting of the non_string parameter.

    The default values of this function are set so as to always return
    a byte string and never raise an error when converting from unicode to
    bytes.  However, when you do not pass an encoding that can validly encode
    the object (or a non-string object), you may end up with output that you
    don't expect.  Be sure you understand the requirements of your data, not
    just ignore errors by passing it through this function.

    :arg obj: Object to convert to a byte string.  this should normally be
        a unicode string.
    :kwarg encoding: What encoding to try using to convert the unicode string
        into bytes.  Defaults to utf8
    :kwarg errors: If errors are given, perform this action.  Defaults to
        'replace' which replaces the error with a '?' character to show
        a character was wunable to be decoded.  Other values are those that
        can be given to the :function:`str.encode()` method.  For instance
        'strict' which raises an exception and 'ignore' which simply omits the
        non-encodable characters.
    :kwargs non_string: How to treat non_string values.  Possible values are:
            :empty: Return an empty byte string
            :strict: Raise a TypeError
            :passthru: Return the object unchanged
            :repr: Attempt to return a byte string of the repr of the
                object
        The Default is 'empty'
    :raises TypeError: if non_string is strict and a non-basestring object is
        passed in or if :param:`non_string` is set to an unknown value
    :returns: byte string or the original object depending on the value of
        non_string.
    '''
    if isinstance(obj, basestring):
        if isinstance(obj, str):
            return obj
        return obj.encode(encoding, errors)
    if non_string == 'empty':
        return ''
    elif non_string == 'passthru':
        return obj
    elif non_string in ('repr', 'strict'):
        obj_repr = repr(obj)
        if isinstance(obj_repr, unicode):
            obj_repr =  obj_repr.encode(encoding, errors)
        else:
            obj_repr = str(obj_repr)
        if non_string == 'repr':
            return obj_repr
        raise TypeError(_('to_bytes was given "%(obj)s" which is neither'
            ' a unicode string or a byte string (str)') % {'obj': obj_repr})

    raise TypeError(_('non_string value, %(param)s, is not set to a valid'
        ' action') % {'param': non_string})
Exemple #9
0
def login(forward_url=None, *args, **kwargs):
    '''Page to become authenticated to the Account System.

    This shows a small login box to type in your username and password
    from the Fedora Account System.

    To use this, replace your current login controller method with::

        from fedora.controllers import login as fc_login

        @expose(template='yourapp.yourlogintemplate', allow_json=True)
        def login(self, forward_url=None, *args, **kwargs):
            login_dict = fc_login(forward_url, args, kwargs)
            # Add anything to the return dict that you need for your app
            return login_dict

    :kwarg: forward_url: The url to send to once authentication succeeds
    '''
    if forward_url:
        if isinstance(forward_url, list):
            forward_url = forward_url.pop(0)
        else:
            del request.params['forward_url']

    if not identity.current.anonymous and identity.was_login_attempted() \
            and not identity.get_identity_errors():
        # User is logged in
        flash(_('Welcome, %s') % identity.current.user_name)
        if request_format() == 'json':
            # When called as a json method, doesn't make any sense to redirect
            # to a page.  Returning the logged in identity is better.
            return dict(user=identity.current.user,
                    _csrf_token=identity.current.csrf_token)
        redirect(forward_url or '/')

    if identity.was_login_attempted():
        msg = _('The credentials you supplied were not correct or '
               'did not grant access to this resource.')
    elif identity.get_identity_errors():
        msg = _('You must provide your credentials before accessing '
               'this resource.')
    else:
        msg = _('Please log in.')
        if not forward_url:
            forward_url = request.headers.get('Referer', '/')

    response.status = 403
    return dict(logging_in=True, message=msg,
        forward_url=forward_url, previous_url=request.path_info,
        original_parameters=request.params)
Exemple #10
0
    def get_owners(self, package, collctn_name=None, collctn_ver=None,
                                  collection=None, collection_ver=None):
        '''Retrieve the ownership information for a package.

        :arg package: Name of the package to retrieve package information about.
        :kwarg collctn_name: Limit the returned information to this collection
            ('Fedora', 'Fedora EPEL', Fedora OLPC', etc)
        :kwarg collctn_ver: If collection is specified, further limit to this
            version of the collection.
        :kwarg collection: old/deprecated argument; use collctn_name
        :kward collection_ver: old/deprecated argument; use collctn_ver
        :raises AppError: If the server returns an error
        :rtype: DictContainer
        :return: dict of ownership information for the package

        .. versionchanged:: 0.3.17
            Rename collection and collection_ver to collctn_name and collctn_ver
        '''
        if (collctn_name and collection) or (collctn_ver and collection_ver):
            warnings.warn(_('collection and collection_ver are deprecated'
                ' names for collctn_name and collctn_ver respectively.'
                '  Ignoring the values given in them.'), DeprecationWarning,
                stacklevel=2)

        if collection and not collctn_name:
            warnings.warn(_('collection has been renamed to collctn_name.\n'
                'Please start using the new name.  collection will go '
                'away in 0.4.x.'), DeprecationWarning, stacklevel=2)
            collctn_name = collection

        if collection_ver and not collctn_ver:
            warnings.warn(_('collection_ver has been renamed to collctn_ver.\n'
                'Please start using the new name.  collection_ver will go '
                'away in 0.4.x.'), DeprecationWarning, stacklevel=2)
            collctn_ver = collection_ver

        method = '/acls/name/%s' % package
        if collctn_name:
            method = method + '/' + collctn_name
            if collctn_ver:
                method = method + '/' + collctn_ver

        response = self.send_request(method)
        if 'status' in response and not response['status']:
            raise AppError(name='PackageDBError', message=response['message'])
        ###FIXME: Really should reformat the data so we show either a
        # dict keyed by collection + version or
        # list of collection, version, owner
        return response
Exemple #11
0
    def __init__(self, base_url='https://admin.fedoraproject.org/accounts/',
            *args, **kwargs):
        '''A threadsafe client to the Fedora Account System.

        This class is optimized to proxy multiple users to the account system.
        ProxyClient is designed to be threadsafe so that code can instantiate
        one instance of the class and use it for multiple requests for
        different users from different threads.

        If you want something that can manage a single user's connection to
        the Account System then use fedora.client.AccountSystem instead.

        :kwargs base_url: Base of every URL used to contact the server.
            Defaults to the Fedora Project FAS instance.
        :kwargs useragent: useragent string to use.  If not given, default to
            "FAS Proxy Client/VERSION"
        :kwarg session_name: name of the cookie to use with session handling
        :kwarg debug: If True, log debug information
        :kwarg insecure: If True, do not check server certificates against
            their CA's.  This means that man-in-the-middle attacks are
            possible against the `BaseClient`. You might turn this option on
            for testing against a local version of a server with a self-signed
            certificate but it should be off in production.
        '''
        if 'useragent' not in kwargs:
            kwargs['useragent'] = 'FAS Proxy Client/%s' % __version__
        if 'session_as_cookie' in kwargs and kwargs['session_as_cookie']:
            # No need to allow this in FasProxyClient as it's deprecated in
            # ProxyClient
            raise TypeError(_('FasProxyClient() got an unexpected keyword'
                ' argument \'session_as_cookie\''))
        kwargs['session_as_cookie'] = False
        super(FasProxyClient, self).__init__(base_url, *args, **kwargs)
Exemple #12
0
    def get_metadata(self, environ):
        log.info(_('Metadata cache miss - refreshing metadata'))
        info = environ.get('FAS_LOGIN_INFO')
        identity = {}

        if info is not None:
            identity.update(info[1])
            identity['session_id'] = info[0]

        for plugin in self._metadata_plugins:
            plugin(identity)

        # we don't define permissions since we don't
        # have any peruser data though other services
        # may wish to add another metadata plugin to do so

        if not identity.has_key('permissions'):
            identity['permissions'] = set()

        # we keep the approved_memberships list because there is also an
        # unapproved_membership field.  The groups field is for repoze.who
        # group checking and may include other types of groups besides
        # memberships in the future (such as special fedora community groups)

        groups = set()
        for g in identity['approved_memberships']:
            groups.add(g['name'])

        identity['groups'] = groups
        return identity
Exemple #13
0
    def validate_identity(self, user_name, password, visit_key):
        '''
        Look up the identity represented by user_name and determine whether the
        password is correct.

        Must return either None if the credentials weren't valid or an object
        with the following properties:

            :user_name: original user name
            :user: a provider dependant object (TG_User or similar)
            :groups: a set of group IDs
            :permissions: a set of permission IDs

        :arg user_name: user_name we're authenticating.  If None, we'll try
            to lookup a username from SSL variables
        :arg password: password to authenticate user_name with
        :arg visit_key: visit_key from the user's session
        '''
        using_ssl = False
        if not user_name and config.get('identity.ssl'):
            if cherrypy.request.headers['X-Client-Verify'] == 'SUCCESS':
                user_name = cherrypy.request.headers['X-Client-CN']
                cherrypy.request.fas_provided_username = user_name
                using_ssl = True

        # pylint: disable-msg=R0201
        # TG identity providers have this method so we can't get rid of it.
        try:
            user = JsonFasIdentity(visit_key, username=user_name,
                    password=password, using_ssl=using_ssl)
        except FedoraServiceError, e:
            self.log.warning(_('Error logging in %(user)s: %(error)s') % {
                'user': user_name, 'error': e})
            return None
Exemple #14
0
    def people_by_id(self):
        '''*Deprecated* Use people_by_key() instead.

        Returns a dict relating user IDs to human_name, email, username,
        and bugzilla email
        '''
        warnings.warn(_("people_by_id() is deprecated and will be removed in"
            " 0.4.  Please port your code to use people_by_key(key='id',"
            " fields=['human_name', 'email', 'username', 'bugzilla_email'])"
            " instead"), DeprecationWarning, stacklevel=2)

        request = self.send_request('/json/user_id', auth=True)
        user_to_id = {}
        people = DictContainer()
        for person_id, username in request['people'].items():
            person_id = int(person_id)
            # change userids from string back to integer
            people[person_id] = {'username': username, 'id': person_id}
            user_to_id[username] = person_id

        # Retrieve further useful information about the users
        request = self.send_request('/group/dump', auth=True)
        for user in request['people']:
            userid = user_to_id[user[0]]
            person = people[userid]
            person['email'] = user[1]
            person['human_name'] = user[2]
            if userid in self.__bugzilla_email:
                person['bugzilla_email'] = self.__bugzilla_email[userid]
            else:
                person['bugzilla_email'] = person['email']

        return people
Exemple #15
0
    def group_data(self, force_refresh=None):
        '''Return administrators/sponsors/users and group type for all groups

        :arg force_refresh: If true, the returned data will be queried from the
            database, as opposed to memcached.
        :raises AppError: if the query failed on the server
        :returns: A dict mapping group names to the group type and the
            user IDs of the administrator, sponsors, and users of the group.

        .. versionadded:: 0.3.8
        '''
        params = {}
        if force_refresh:
            params['force_refresh'] = True

        try:
            request = self.send_request('json/fas_client/group_data',
                req_params=params, auth=True)
            if request['success']:
                return request['data']
            else:
                raise AppError(message=_('FAS server unable to retrieve group'
                    ' members'), name='FASError')
        except FedoraServiceError:
            raise
Exemple #16
0
 def keep_alive(self, session_id):
     log.info(_('Keep alive cache miss'))
     try:
         linfo = self.fas.get_user_info({'session_id': session_id})
     except AuthError, e:
         log.warning(e)
         return None
Exemple #17
0
    def __retrieve_user(self):
        '''Attempt to load the user from the visit_key.

        :returns: a user or None
        '''
        if self.debug:
            import inspect
            caller = inspect.getouterframes(inspect.currentframe())[2][3]
            self.log.debug('JSONFASPROVIDER.send_request caller: %s' % caller)

        if self._retrieved_user:
            return self._retrieved_user
        # I hope this is a safe place to double-check the SSL variables.
        # TODO: Double check my logic with this - is it unnecessary to
        # check that the username matches up?
        if self.using_ssl:
            if cherrypy.request.headers['X-Client-Verify'] != 'SUCCESS':
                self.logout()
                return None
            # Retrieve the user information differently when using ssl
            try:
                person = fas.person_by_username(self.username, auth=True)
            except Exception, e: # pylint: disable-msg=W0703
                # :W0703: Any errors have to result in no user being set.  The
                # rest of the framework doesn't know what to do otherwise.
                self.log.warning(_('jsonfasprovider, ssl, returned errors'
                    ' from send_request: %s') % e)
                person = None
            self._retrieved_user = person or None
            return self._retrieved_user
Exemple #18
0
    def _del_session_cookie(self):
        '''**Deprecated** Use session_id instead.

        Delete the session cookie from the filesystem.
        '''
        warnings.warn(_('session_cookie is deprecated, use session_id'
            ' instead'), DeprecationWarning, stacklevel=2)
        del(self.session_id)
Exemple #19
0
 def update_queued_visits(self, queue):
     '''Update the visit information on the server'''
     log.debug('JsonFasVisitManager.update_queued_visits: enter')
     # Hit any URL in fas with each visit_key to update the sessions
     for visit_key in queue:
         log.info(_('updating visit (%s)'), visit_key)
         self.fas.refresh_session(visit_key)
     log.debug('JsonFasVisitManager.update_queued_visits: exit')
Exemple #20
0
    def extract_csrf_token(self, request):
        '''Extract and remove the CSRF token from a given
        :class:`webob.Request`
        '''
        csrf_token = None

        if self.csrf_token_id in request.GET:
            log.debug(_("%(token)s in GET") % {'token': self.csrf_token_id})
            csrf_token = request.GET[self.csrf_token_id]
            del(request.GET[self.csrf_token_id])
            request.query_string = '&'.join(['%s=%s' % (k, v) for k, v in
                                             request.GET.items()])

        if self.csrf_token_id in request.POST:
            log.debug(_("%(token)s in POST") % {'token': self.csrf_token_id})
            csrf_token = request.POST[self.csrf_token_id]
            del(request.POST[self.csrf_token_id])

        return csrf_token
Exemple #21
0
 def group_by_name(self, groupname):
     '''Returns a group object based on its name'''
     params = {'groupname': groupname}
     request = self.send_request('json/group_by_name', auth = True,
             req_params = params)
     if request['success']:
         return request['group']
     else:
         raise AppError(message=_('FAS server unable to retrieve group %s')
                 % groupname, name='FASError')
Exemple #22
0
    def __init__(self, base_url, useragent=None, session_name='tg-visit',
            session_as_cookie=True, debug=False, insecure=False):
        '''Create a client configured for a particular service.

        :arg base_url: Base of every URL used to contact the server

        :kwarg useragent: useragent string to use.  If not given, default to
            "Fedora ProxyClient/VERSION"
        :kwarg session_name: name of the cookie to use with session handling
        :kwarg session_as_cookie: If set to True, return the session as a
            SimpleCookie.  If False, return a session_id.  This flag allows us
            to maintain compatibility for the 0.3 branch.  In 0.4, code will
            have to deal with session_id's instead of cookies.
        :kwarg debug: If True, log debug information
        :kwarg insecure: If True, do not check server certificates against
            their CA's.  This means that man-in-the-middle attacks are
            possible against the `BaseClient`. You might turn this option on
            for testing against a local version of a server with a self-signed
            certificate but it should be off in production.
        '''
        # Setup our logger
        self._log_handler = logging.StreamHandler()
        self.debug = debug
        format = logging.Formatter("%(message)s")
        self._log_handler.setFormatter(format)
        self.log.addHandler(self._log_handler)

        self.log.debug(_('proxyclient.__init__:entered'))
        if base_url[-1] != '/':
            base_url = base_url +'/'
        self.base_url = base_url
        self.useragent = useragent or 'Fedora ProxyClient/%(version)s' % {
                'version': __version__}
        self.session_name = session_name
        self.session_as_cookie = session_as_cookie
        if session_as_cookie:
            warnings.warn(_('Returning cookies from send_request() is'
                ' deprecated and will be removed in 0.4.  Please port your'
                ' code to use a session_id instead by calling the ProxyClient'
                ' constructor with session_as_cookie=False'),
                DeprecationWarning, stacklevel=2)
        self.insecure = insecure
        self.log.debug(_('proxyclient.__init__:exited'))
Exemple #23
0
    def edit_package(self, pkg, owner=None, description=None,
            branches=None, cc_list=None, comaintainers=None, groups=None):
        '''Edit a package.

        :arg pkg: Name of the package to edit
        :kwarg owner: If set, make this person the owner of both branches
        :kwarg description: If set, make this the description of both branches
        :kwarg branches: List of branches to operate on
        :kwarg cc_list: If set, list or tuple of usernames to watch the
            package.
        :kwarg comaintainers: If set, list or tuple of usernames to comaintain
            the package.
        :kwarg groups: If set, list or tuple of group names that can commit to
            the package.
        :raises AppError: If the server returns an error

        This method takes information about a package and either edits the
        package to reflect the changes to information.

        Note: This method will be going away in favor of methods that do
        smaller chunks of work:

        1) A method to add a new branch
        2) A method to edit an existing package
        3) A method to edit an existing branch

        .. versionadded:: 0.3.13
        '''
        # Change the branches, owners, or anything else that needs changing
        data = {}
        if owner:
            data['owner'] = owner
        if description:
            data['summary'] = description
        if cc_list:
            data['ccList'] = simplejson.dumps(cc_list)
        if comaintainers:
            data['comaintList'] = simplejson.dumps(comaintainers)

        # Parse the groups information
        if groups:
            data['groups'] = simplejson.dumps(groups)

        # Parse the Branch abbreviations into collections
        if branches:
            data['collections'] = []
            data['collections'] = branches

        # Request the changes
        response = self.send_request('/acls/dispatcher/edit_package/%s'
                % pkg, auth=True, req_params=data)
        if 'status' in response and not response['status']:
            raise AppError(name='PackageDBError', message=_('Unable to save'
                ' all information for %(pkg)s: %(msg)s') % {'pkg': pkg,
                    'msg': response['message']})
def _syncdb_handler(sender, **kwargs):
    # Import FAS groups
    verbosity = kwargs.get('verbosity', 1)
    if verbosity > 0:
        print(_('Loading FAS groups...'))
    try:
        gl = connection.group_list({'username': settings.FAS_USERNAME,
                                    'password': settings.FAS_PASSWORD})
    except AuthError:
        if verbosity > 0:
            print(_('Unable to load FAS groups. Did you set '
                    'FAS_USERNAME and FAS_PASSWORD?'))
    else:
        groups = gl[1]['groups']
        for group in groups:
            _new_group(group)
        if verbosity > 0:
            print(_('FAS groups loaded. Don\'t forget to set '
                    'FAS_USERNAME and FAS_PASSWORD to a low-privilege '
                    'account.'))
Exemple #25
0
    def __save_ids(self, save):
        '''Save the cached ids file.

        :arg save: The dict of usernames to ids to save.
        '''
        # Make sure the directory exists
        if not path.isdir(SESSION_DIR):
            try:
                os.mkdir(SESSION_DIR, 0755)
            except OSError, e:
                self.log.warning(_('Unable to create %(dir)s: %(error)s') %
                    {'dir': SESSION_DIR, 'error': str(e)})
Exemple #26
0
    def remember(self, environ, identity):
        log.info(_('In remember()'))
        req = webob.Request(environ)
        result = []

        linfo = environ.get('FAS_LOGIN_INFO')
        if isinstance(linfo, tuple):
            session_id = linfo[0]
            set_cookie = '%s=%s; Path=/;' % (self.session_cookie, session_id)
            result.append(('Set-Cookie', set_cookie))
            return result
        return None
Exemple #27
0
 def login(self, username, password):
     data = self.send_request('api.php', req_params={
             'action': 'login',
             'format': 'json',
             'lgname': username,
             'lgpassword': password,
             })
     if 'lgtoken' not in data.get('login', {}):
         raise AuthError(_('Login failed: %s') % data)
     #self.session_id = data['login']['lgtoken']
     #self.username = data['login']['lgusername']
     self.check_api_limits()
     return data
Exemple #28
0
    def forget(self, environ, identity):
        log.info(_('In forget()'))
        # return a expires Set-Cookie header
        req = webob.Request(environ)

        linfo = environ.get('FAS_LOGIN_INFO')
        if isinstance(linfo, tuple):
            session_id = linfo[0]
            log.info(_('Forgetting login data for cookie %(s_id)s') %
                    {'s_id': session_id})

            self.fas.logout(session_id)

            result = []
            fas_cache.remove_value(key=session_id + '_identity')
            expired = '%s=\'\'; Path=/; Expires=Sun, 10-May-1971 11:59:00 GMT'\
                    % self.session_cookie
            result.append(('Set-Cookie', expired))
            environ['FAS_LOGIN_INFO'] = None
            return result

        return None
Exemple #29
0
    def candidates(self):
        """ Get a list list of update candidates.

        This method is a generator that returns a list of koji builds that
        could potentially be pushed as updates.
        """
        if not self.username:
            raise BodhiClientException(_('You must specify a username'))
        data = self.send_request('candidate_tags')
        koji = self.get_koji_session(login=False)
        for tag in data['tags']:
            for build in koji.listTagged(tag, latest=True):
                if build['owner_name'] == self.username:
                    yield build
Exemple #30
0
    def get_package_list(self, collctn=None, collectn=None):
        '''Retrieve a list of all package names in a collection.

        :kwarg collctn: Collection to look for packages in.  This is a collctn
            shortname like 'devel' or 'F-13'.  If unset, return packages in
            all collections
        :kwarg collectn: *Deprecated*.  Please use collctn instead
        :returns: list of package names present in the collection.

        .. versionadded:: 0.3.15

        .. versionchanged:: 0.3.17
            Rename collectn to collctn
        '''
        if (collctn and collectn):
            warnings.warn(_('collectn is a deprecated name for'
                    ' collctn.\nIgnoring the value of collectn.'),
                    DeprecationWarning, stacklevel=2)

        if collectn and not collctn:
            warnings.warn(_('collectn has been renamed to collctn.\n'
                    'Please start using the new name.  collectn will go'
                    ' away in 0.4.x.'), DeprecationWarning, stacklevel=2)
            collctn = collectn

        params = {'tg_paginate_limit': '0'}
        if collctn:
            try:
                collctn_id = self.branches[collctn]['id']
            except KeyError:
                raise PackageDBError(_('Collection shortname %(collctn)s'
                    ' is unknown.') % {'collctn': collctn})
            data = self.send_request('/collections/name/%s/' % collctn, params)
        else:
            data = self.send_request('/acls/list/*', params)
        names = [p['name'] for p in data.packages]
        return names
Exemple #31
0
    def _get_session_cookie(self):
        '''**Deprecated** Use session_id instead.

        Attempt to retrieve the session cookie from the filesystem.

        :Returns: user's session cookie
        '''
        warnings.warn(_('session_cookie is deprecated, use session_id'
            ' instead'), DeprecationWarning, stacklevel=2)
        session_id = self.session_id
        if not session_id:
            return ''
        cookie = Cookie.SimpleCookie()
        cookie[self.session_name] = session_id
        return cookie
Exemple #32
0
'''
Information about this python-fedora release
'''

from fedora import _

NAME = 'python-fedora'
VERSION = '0.3.32.90'
DESCRIPTION = _('Python modules for interacting with Fedora Services')
LONG_DESCRIPTION = _('''
The Fedora Project runs many different services.  These services help us to
package software, develop new programs, and generally put together the distro.
This package contains software that helps us do that.
''')
AUTHOR = 'Toshio Kuratomi, Luke Macken, Ricky Elrod'
EMAIL = '*****@*****.**'
COPYRIGHT = '2007-2013 Red Hat, Inc.'
URL = 'https://fedorahosted.org/python-fedora'
DOWNLOAD_URL = 'https://fedorahosted.org/releases/p/y/python-fedora/'
LICENSE = 'LGPLv2+'