Example #1
0
        def check_crendential(l, r):
            # Check results
            if len(r) != 1:
                logger.debug("user [%s] not found in LDAP", username)
                return None

            # Bind using the user credentials. Throws an exception in case of
            # error.
            l.simple_bind_s(r[0][0], password)
            try:
                logger.info("user [%s] found in LDAP", username)

                # Verify the shadow expire
                if self.check_shadow_expire:
                    shadow_expire = self._attr_shadow_expire(r)
                    # Convert nb. days into seconds.
                    if shadow_expire and shadow_expire * 24 * 60 * 60 < time.time():
                        logger.warn("user account %s expired: %s", username, shadow_expire)
                        raise RdiffError(_('User account %s expired.' % username))

                # Get username
                dn = r[0][0]
                new_username = self._decode(r[0][1][self.attribute][0])

                # Verify if the user is member of the required group
                if self.require_group:
                    value = dn if self.group_attribute_is_dn else new_username
                    logger.info("check if user [%s] is member of [%s]", value, self.require_group)
                    if not l.compare_s(self.require_group, self.group_attribute, value):
                        raise RdiffError(_('Permissions denied for user account %s.' % username))
            finally:
                l.unbind_s()
            # Return the username
            return new_username
Example #2
0
    def _handle_add(self, filename, **kwargs):
        """
        Called to add a new key to an authorized_keys file.
        """
        assert 'key' in kwargs, "key is missing"

        # Validate the content of the key.
        try:
            key = authorizedkeys.check_publickey(kwargs['key'])
        except:
            raise RdiffWarning(_("Invalid SSH key."))

        # Check if already exists
        if authorizedkeys.exists(filename, key):
            raise RdiffWarning(_("SSH key already exists."))

        # Check size.
        if key.size and key.size < 2048:
            raise RdiffWarning(_("SSH key is too short. RSA key of at least 2048 bits is required."))

        # Add comment to the key.
        comment = key.comment
        if 'title' in kwargs:
            comment = kwargs['title'].strip()

        key = authorizedkeys.KeySplit(
            lineno=key.lineno,
            options=key.options,
            keytype=key.keytype,
            key=key.key,
            comment=comment)

        # Add key to file
        _logger.info("add key [%s] to [%s]", key, filename)
        authorizedkeys.add(filename, key)
Example #3
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Get user root directory
        user_root = self.app.userdb.get_user_root(self.app.currentuser.username)
        user_root_b = encode_s(user_root)
        filename = os.path.join(user_root_b, b'.ssh', b'authorized_keys')

        # Handle action
        params = {}
        if 'action' in kwargs:
            try:
                action = kwargs['action']
                if action == 'add':
                    self._handle_add(filename, **kwargs)
                elif action == 'delete':
                    self._handle_delete(filename, **kwargs)
            except ValueError as e:
                params['error'] = unicode(e)
            except Exception as e:
                _logger.warn("unknown error processing action", exc_info=True)
                params['error'] = _("Unknown error")

        # Get SSH keys if file exists.
        params["sshkeys"] = []
        if os.access(filename, os.R_OK):
            try:
                params["sshkeys"] = [
                    {'title': key.comment or (key.keytype + ' ' + key.key[:18]),
                     'fingerprint': key.fingerprint,
                     'lineno': key.lineno}
                    for key in authorizedkeys.read(filename)]
            except IOError:
                params['error'] = _("error reading SSH keys file")
                _logger.warn("error reading SSH keys file [%s]", filename)

        return "prefs_sshkeys.html", params
Example #4
0
    def _handle_set_profile_info(self, **kwargs):
        """
        Called when changing user profile.
        """
        # Check data.
        if 'email' not in kwargs:
            raise RdiffWarning(_("Email is undefined."))

        # Check if email update is supported
        if not self.app.userdb.supports('set_email'):
            return {'error': _("Email update is not supported.")}

        # Parse the email value to extract a valid email. The following method
        # return an empty string if the email is not valid. This RFC also accept
        # local email address without '@'. So we add verification for '@'
        if not PATTERN_EMAIL.match(kwargs['email'].lower()):
            raise RdiffWarning(_("Invalid email."))

        # Update the user's email
        assert self.app.currentuser
        username = self.app.currentuser.username
        email = kwargs['email']
        _logger.info("updating user [%s] email [%s]", username, email)
        self.app.currentuser.email = kwargs['email']

        return {'success': _("Profile updated successfully.")}
Example #5
0
    def _handle_set_password(self, **kwargs):
        """
        Called when changing user password.
        """
        if 'current' not in kwargs or not kwargs['current']:
            raise RdiffWarning(_("Current password is missing."))
        if 'new' not in kwargs or not kwargs['new']:
            raise RdiffWarning(_("New password is missing."))
        if 'confirm' not in kwargs or not kwargs['confirm']:
            raise RdiffWarning(_("Confirmation password is missing."))

        # Check if confirmation is valid.
        if kwargs['new'] != kwargs['confirm']:
            return {
                'error':
                _("The new password and its confirmation do not match.")
            }

        # Update user password
        user = self.app.currentuser.username
        _logger.info("updating user [%s] password", user)
        self.app.userdb.set_password(user,
                                     kwargs['new'],
                                     old_password=kwargs['current'])
        return {'success': _("Password updated successfully.")}
Example #6
0
    def _handle_add(self, filename, **kwargs):
        """
        Called to add a new key to an authorized_keys file.
        """
        assert 'key' in kwargs, "key is missing"

        # Validate the content of the key.
        try:
            key = authorizedkeys.check_publickey(kwargs['key'])
        except:
            raise RdiffWarning(_("Invalid SSH key."))

        # Check if already exists
        if authorizedkeys.exists(filename, key):
            raise RdiffWarning(_("SSH key already exists."))

        # Check size.
        if key.size and key.size < 2048:
            raise RdiffWarning(_("SSH key is too short. RSA key of at least 2048 bits is required."))

        # Add comment to the key.
        comment = key.comment
        if 'title' in kwargs:
            comment = kwargs['title'].strip()

        key = authorizedkeys.KeySplit(
            lineno=key.lineno,
            options=key.options,
            keytype=key.keytype,
            key=key.key,
            comment=comment)

        # Add key to file
        _logger.info("add key [%s] to [%s]", key, filename)
        authorizedkeys.add(filename, key)
Example #7
0
    def _handle_set_profile_info(self, **kwargs):
        """
        Called when changing user profile.
        """
        # Check data.
        if 'email' not in kwargs:
            raise ValueError(_("email is undefined"))

        # Check if email update is supported
        if not self.app.userdb.supports('set_email'):
            return {'error': _("Email update is not supported.")}

        # Parse the email value to extract a valid email. The following method
        # return an empty string if the email is not valid. This RFC also accept
        # local email address without '@'. So we add verification for '@'
        if not PATTERN_EMAIL.match(kwargs['email'].lower()):
            raise ValueError(_("invalid email"))

        # Update the user's email
        if not self.app.currentuser:
            raise RdiffError(_("invalid state"))

        username = self.app.currentuser.username
        email = kwargs['email']
        _logger.info("updating user [%s] email [%s]", username, email)
        self.app.userdb.set_email(username, kwargs['email'])

        return {'success': _("Profile updated successfully.")}
Example #8
0
    def index(self, path=b'', new_encoding=None):
        """
        Update repository encoding via Ajax.
        """
        self.assertIsInstance(path, bytes)
        self.assertTrue(new_encoding)

        _logger.debug("update repo [%r] settings [%r]", path, new_encoding)

        # Check user permissions
        repo_obj = self.validate_user_path(path)[0]

        # Validate the encoding value
        new_codec = encodings.search_function(new_encoding.lower())
        if not new_codec:
            raise cherrypy.HTTPError(400, _("invalid encoding value"))

        new_encoding = new_codec.name
        if not isinstance(new_encoding, str):
            # Python 2
            new_encoding = new_encoding.decode('ascii')

        # Update the repository encoding
        _logger.info("updating repository [%s] encoding [%s]", repo_obj, new_encoding)
        repo_obj.set_encoding(new_encoding)

        return _("Updated")
Example #9
0
    def index(self, path=b'', new_encoding=None):
        """
        Update repository encoding via Ajax.
        """
        self.assertIsInstance(path, bytes)
        self.assertTrue(new_encoding)

        _logger.debug("update repo [%r] settings [%r]", path, new_encoding)

        # Check user permissions
        repo_obj = self.validate_user_path(path)[0]

        # Validate the encoding value
        new_codec = encodings.search_function(new_encoding.lower())
        if not new_codec:
            raise cherrypy.HTTPError(400, _("invalid encoding value"))

        new_encoding = new_codec.name
        if not isinstance(new_encoding, str):
            # Python 2
            new_encoding = new_encoding.decode('ascii')

        # Update the repository encoding
        _logger.info("updating repository [%s] encoding [%s]", repo_obj,
                     new_encoding)
        repo_obj.set_encoding(new_encoding)

        return _("Updated")
Example #10
0
    def _users_handle_action(self, action, username, email, password,
                             user_root, is_admin):

        success = ""

        # We need to change values. Change them, then give back that main
        # page again, with a message
        if username == self.app.currentuser.username:
            # Don't allow the user to changes it's "admin" state.
            is_admin = self.app.currentuser.is_admin

        is_admin = str(is_admin).lower() in ['true', '1']

        # Fork the behaviour according to the action.
        if action == "edit":
            user = self.app.userdb.get_user(username)
            logger.info("updating user [%s] info", user)
            if password:
                self.app.userdb.set_password(username,
                                             password,
                                             old_password=None)
            user.user_root = user_root
            user.is_admin = is_admin
            # Avoid updating the email fields is it didn'T changed. see pdsl/minarca#187
            if email != user.email:
                user.email = email
            success = _("User information modified successfully.")

            # Check and update user directory
            self._check_user_root_dir(user_root)
            rdw_spider_repos.find_repos_for_user(user)

        elif action == "add":

            if username == "":
                raise RdiffWarning(_("The username is invalid."))
            logger.info("adding user [%s]", username)

            user = self.app.userdb.add_user(username, password)
            user.user_root = user_root
            user.is_admin = is_admin
            user.email = email

            # Check and update user directory
            self._check_user_root_dir(user_root)
            rdw_spider_repos.find_repos_for_user(user)
            success = _("User added successfully.")

        if action == "delete":
            user = self.app.userdb.get_user(username)
            if username == self.app.currentuser.username:
                raise RdiffWarning(_("You cannot remove your own account!."))
            logger.info("deleting user [%s]", username)
            self.app.userdb.delete_user(user)
            success = _("User account removed.")

        # Return messages
        return {'success': success}
Example #11
0
    def _users_handle_action(self, action, username, email, password,
                             user_root, is_admin):

        success = ""

        # We need to change values. Change them, then give back that main
        # page again, with a message
        if username == self.app.currentuser.username:
            # Don't allow the user to changes it's "admin" state.
            is_admin = self.app.currentuser.is_admin

        is_admin = str(is_admin).lower() in ['true', '1']

        # Fork the behaviour according to the action.
        if action == "edit":
            user = self.app.userdb.get_user(username)
            logger.info("updating user [%s] info", user)
            if password:
                self.app.userdb.set_password(username, password, old_password=None)
            user.user_root = user_root
            user.is_admin = is_admin
            # Avoid updating the email fields is it didn'T changed. see pdsl/minarca#187
            if email != user.email:
                user.email = email
            success = _("User information modified successfully.")

            # Check and update user directory
            self._check_user_root_dir(user_root)
            rdw_spider_repos.find_repos_for_user(user)

        elif action == "add":

            if username == "":
                raise RdiffWarning(_("The username is invalid."))
            logger.info("adding user [%s]", username)

            user = self.app.userdb.add_user(username, password)
            user.user_root = user_root
            user.is_admin = is_admin
            user.email = email

            # Check and update user directory
            self._check_user_root_dir(user_root)
            rdw_spider_repos.find_repos_for_user(user)
            success = _("User added successfully.")

        if action == "delete":
            user = self.app.userdb.get_user(username)
            if username == self.app.currentuser.username:
                raise RdiffWarning(_("You cannot remove your own account!."))
            logger.info("deleting user [%s]", username)
            self.app.userdb.delete_user(user)
            success = _("User account removed.")

        # Return messages
        return {'success': success}
Example #12
0
 def check_username_and_password(self, username, password):
     """Validate user credentials."""
     logger.debug("check credentials for [%s]", username)
     try:
         userobj = cherrypy.request.app.userdb.login(username, password)  # @UndefinedVariable
     except:
         logger.exception("fail to validate user credential.",)
         raise RdiffWarning(_("Fail to validate user credential."))
     if not userobj:
         logger.warning("invalid username or password")
         raise RdiffWarning(_("Invalid username or password."))
     return userobj
Example #13
0
    def set_password(self, username, password, old_password=None):
        assert isinstance(username, str)
        assert old_password is None or isinstance(old_password, str)
        assert isinstance(password, str)
        if not password:
            raise RdiffError(_("Password can't be empty."))

        # Check old password value.
        if old_password and not self.are_valid_credentials(username, old_password):
            raise RdiffError(_("Wrong password."))

        # Update password.
        self._set_user_field(username, 'Password', self._hash_password(password))
Example #14
0
 def check_username_and_password(self, username, password):
     """Validate user credentials."""
     logger.info("check credentials for [%s]", username)
     try:
         userobj = cherrypy.request.app.userdb.login(
             username, password)  # @UndefinedVariable
     except:
         logger.exception("fail to validate user credential")
         raise RdiffWarning(_("Fail to validate user credential."))
     if not userobj:
         logger.warning("invalid username [%s] or password", username)
         raise RdiffWarning(_("Invalid username or password."))
     return userobj
Example #15
0
    def _handle_set_encoding(self, repo_obj, **kwargs):
        """
        Change the encoding of the repository.
        """
        # Validate the encoding value
        new_encoding = kwargs.get('encoding')
        new_encoding = unicode(encodings.normalize_encoding(new_encoding)).lower()
        if new_encoding not in self._get_encodings():
            raise ValueError(_("invalid encoding value"))

        # Update the repository encoding
        _logger.info("updating repository [%s] encoding [%s]", repo_obj, new_encoding)
        repo_obj.set_encoding(new_encoding)

        return {'success': _("Repository updated successfully with new encoding.")}
Example #16
0
    def set_password(self, username, password, old_password=None):
        assert isinstance(username, str)
        assert old_password is None or isinstance(old_password, str)
        assert isinstance(password, str)
        if not password:
            raise RdiffError(_("Password can't be empty."))

        # Check old password value.
        if old_password and not self.are_valid_credentials(
                username, old_password):
            raise RdiffError(_("Wrong password."))

        # Update password.
        self._set_user_field(username, 'Password',
                             self._hash_password(password))
Example #17
0
    def do_check(self):
        """Assert username. Raise redirect, or return True if request handled."""
        request = cherrypy.serving.request
        response = cherrypy.serving.response

        if not self.is_login():
            url = cherrypy.url(qs=request.query_string)

            # If browser requesting text/plain. It's probably an Ajax call, don't
            # redirect and raise an exception.
            mtype = cherrypy.tools.accept.callable(['text/html', 'text/plain'])  # @UndefinedVariable
            if mtype == 'text/plain':
                logger.debug('No username, requesting plain text, routing to 403 error from_page %(url)r', locals())
                raise cherrypy.HTTPError(403, _("Not logged in"))

            logger.debug('No username, routing to login_screen with from_page %(url)r', locals())
            response.body = self.login_screen(url)
            if "Content-Length" in response.headers:
                # Delete Content-Length header so finalize() recalcs it.
                del response.headers["Content-Length"]
            return True

        # Define the value of request.login to later in code we can reuse it.
        username = cherrypy.session[self.session_key]  # @UndefinedVariable
        userobj = cherrypy.request.app.userdb.get_user(username)  # @UndefinedVariable
        if not userobj:
            raise cherrypy.HTTPError(403)
        logger.debug('Setting request.login to %r', userobj)
        cherrypy.serving.request.login = userobj
Example #18
0
 def set_password(self, user, password, old_password=None):
     # Check if user exists in database
     db = self.find_user_database(user)
     if not db:
         raise InvalidUserError(user)
     # Try to update the user password.
     store = self.find_user_store(user)
     if store and not store.supports('set_password'):
         raise RdiffError(_("""The authentication backend for user %s does
         not support setting the password""" % user))
     elif not store:
         store = self._get_supporting_store('set_password')
     if not store:
         raise RdiffError(_("none of the IPasswordStore supports setting the password"))
     store.set_password(user, password, old_password)
     self._notify('password_changed', user, password)
Example #19
0
    def index(self, path=b"", limit='10', **kwargs):
        self.assertIsInstance(path, bytes)
        self.assertIsInt(limit)
        limit = int(limit)

        logger.debug("history [%r]", path)

        repo_obj = self.validate_user_path(path)[0]
        assert isinstance(repo_obj, librdiff.RdiffRepo)

        # Set up warning about in-progress backups, if necessary
        warning = False
        status = repo_obj.status
        if status[0] != 'ok':
            warning = status[1] + ' ' + _("The displayed data may be inconsistent.")

        parms = {
            "limit": limit,
            "repo_name": repo_obj.display_name,
            "repo_path": repo_obj.path,
            "history_entries": repo_obj.get_history_entries(numLatestEntries=limit, reverse=True),
            "warning": warning,
        }

        return self._compile_template("history.html", **parms)
Example #20
0
 def _handle_update_repos(self):
     """
     Called to refresh the user repos.
     """
     rdw_spider_repos.find_repos_for_user(self.app.currentuser.username,
                                          self.app.userdb)
     return {'success': _("Repositories successfully updated.")}
Example #21
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Process the parameters.
        params = dict()
        action = kwargs.get('action')
        if action:
            try:
                if action == "set_profile_info":
                    params = self._handle_set_profile_info(**kwargs)
                elif action == "set_password":
                    params = self._handle_set_password(**kwargs)
                elif action == "update_repos":
                    params = self._handle_update_repos()
                else:
                    _logger.info("unknown action: %s", action)
                    raise cherrypy.NotFound("Unknown action")
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                _logger.warning("unknown error processing action",
                                exc_info=True)
                params['error'] = _("Unknown error")

        user = self.app.currentuser.username
        params.update({
            'email':
            self.app.currentuser.email,
            'supports_set_email':
            self.app.userdb.supports('set_email', user),
            'supports_set_password':
            self.app.userdb.supports('set_password', user),
        })
        return "prefs_general.html", params
Example #22
0
    def do_check(self):
        """Assert username. Raise redirect, or return True if request handled."""
        request = cherrypy.serving.request
        response = cherrypy.serving.response

        if not self.is_login():
            url = cherrypy.url(qs=request.query_string)

            # If browser requesting text/plain. It's probably an Ajax call, don't
            # redirect and raise an exception.
            mtype = cherrypy.tools.accept.callable(['text/html', 'text/plain'
                                                    ])  # @UndefinedVariable
            if mtype == 'text/plain':
                logger.debug(
                    'No username, requesting plain text, routing to 403 error from_page %(url)r',
                    locals())
                raise cherrypy.HTTPError(403, _("Not logged in"))

            logger.debug(
                'No username, routing to login_screen with from_page %(url)r',
                locals())
            response.body = self.login_screen(url)
            if "Content-Length" in response.headers:
                # Delete Content-Length header so finalize() recalcs it.
                del response.headers["Content-Length"]
            return True

        # Define the value of request.login to later in code we can reuse it.
        username = cherrypy.session[self.session_key]  # @UndefinedVariable
        userobj = cherrypy.request.app.userdb.get_user(
            username)  # @UndefinedVariable
        if not userobj:
            raise cherrypy.HTTPError(403)
        logger.debug('Setting request.login to %r', userobj)
        cherrypy.serving.request.login = userobj
Example #23
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Process the parameters.
        params = dict()
        action = kwargs.get('action')
        if action:
            try:
                if action == "set_profile_info":
                    params = self._handle_set_profile_info(**kwargs)
                elif action == "set_password":
                    params = self._handle_set_password(**kwargs)
                elif action == "update_repos":
                    params = self._handle_update_repos()
                else:
                    _logger.info("unknown action: %s", action)
                    raise cherrypy.NotFound("Unknown action")
            except RdiffError as e:
                params['error'] = unicode(e)
            except ValueError as e:
                params['error'] = unicode(e)
            except Exception as e:
                _logger.warn("unknown error processing action", exc_info=True)
                params['error'] = _("Unknown error")

        user = self.app.currentuser.username
        params.update({
            'email': self.app.currentuser.email,
            'supports_set_email': self.app.userdb.supports('set_email', user),
            'supports_set_password': self.app.userdb.supports('set_password', user),
        })
        return "prefs_general.html", params
Example #24
0
    def send_notifications(self):
        """
        Loop trough all the user repository and send notifications.
        """

        now = librdiff.RdiffTime()

        def _user_repos():
            """Return a generator trought user repos to be notified."""
            for user in self.app.userdb.list():
                # Check if user has email.
                if not user.email:
                    continue
                # Identify old repo for current user.
                old_repos = []
                for repo in user.repo_list:
                    # Check if repo has age configured (in days)
                    maxage = repo.maxage
                    if not maxage or maxage <= 0:
                        continue
                    # Check repo age.
                    r = librdiff.RdiffRepo(user.user_root, repo.name)
                    if r.last_backup_date < (now - datetime.timedelta(days=maxage)):
                        old_repos.append(r)
                # Return an item only if user had old repo
                if old_repos:
                    yield user, old_repos

        # For each candidate, send mail.
        for user, repos in _user_repos():
            parms = {'user': user, 'repos': repos}
            self.send_mail(user, _('Notification'), 'email_notification.html', **parms)
Example #25
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Process the parameters.
        params = dict()
        action = kwargs.get('action')
        if action:
            try:
                if action == "set_notification_info":
                    self._handle_set_notification_info(**kwargs)
                else:
                    _logger.info("unknown action: %s", action)
                    raise cherrypy.NotFound("Unknown action")
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                _logger.warning("unknown error processing action", exc_info=True)
                params['error'] = _("Unknown error")

        params.update({
            'email': self.app.currentuser.email,
            'repos': [
                {'name': r.name, 'maxage': r.maxage}
                for r in self.app.currentuser.repo_list],
        })
        return "prefs_notification.html", params
Example #26
0
    def _handle_delete(self, filename, **kwargs):
        """
        Called for delete a key from an authorized_keys file.
        """

        # Check if key is valid.
        if 'key' not in kwargs:
            raise ValueError(_("key is missing"))
        try:
            lineno = int(kwargs['key'])
        except ValueError:
            raise ValueError(_("key is invalid"))

        # Remove the key
        _logger.info("removing key [%s] from [%s]", lineno, filename)
        authorizedkeys.remove(filename, lineno)
Example #27
0
    def index(self, path=b"", limit='10', **kwargs):
        self.assertIsInstance(path, bytes)
        self.assertIsInt(limit)
        limit = int(limit)

        logger.debug("history [%r]", path)

        repo_obj = self.validate_user_path(path)[0]
        assert isinstance(repo_obj, librdiff.RdiffRepo)

        # Set up warning about in-progress backups, if necessary
        warning = False
        status = repo_obj.status
        if status[0] != 'ok':
            warning = status[1] + ' ' + _(
                "The displayed data may be inconsistent.")

        parms = {
            "limit":
            limit,
            "repo_name":
            repo_obj.display_name,
            "repo_path":
            repo_obj.path,
            "history_entries":
            repo_obj.get_history_entries(numLatestEntries=limit, reverse=True),
            "warning":
            warning,
        }

        return self._compile_template("history.html", **parms)
Example #28
0
    def users(self, userfilter=u"", usersearch=u"", action=u"", username=u"",
              email=u"", password=u"", user_root=u"", is_admin=u""):

        # Check if user is an administrator
        if not self.app.currentuser or not self.app.currentuser.is_admin:
            raise cherrypy.HTTPError(403)

        self.assertIsInstance(userfilter, str)
        self.assertIsInstance(usersearch, str)

        # If we're just showing the initial page, just do that
        params = {}
        if self._is_submit():
            try:
                params = self._users_handle_action(action, username,
                                                   email, password, user_root,
                                                   is_admin)
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                logger.warning("unknown error", exc_info=True)
                params['error'] = _("Unknown error")

        # Get page parameters
        params.update(
            self._users_get_params_for_page(userfilter, usersearch))

        # Build users page
        return self._compile_template("admin_users.html", **params)
Example #29
0
    def default(self, path=b"", date=None, kind=None, usetar=None):
        self.assertIsInstance(path, bytes)
        self.assertIsInstance(date, str)
        self.assertTrue(kind is None or kind in ARCHIVERS)
        self.assertTrue(usetar is None or isinstance(usetar, str))

        logger.debug("restoring [%r][%s]", path, date)

        # The path wont have leading and trailing "/".
        (path, file_b) = os.path.split(path)
        if not path:
            path = file_b
            file_b = b""

        # Check user access to repo / path.
        (repo_obj, path_obj) = self.validate_user_path(path)

        # Get the restore date
        try:
            rdw_helpers.rdwTime(int(date))
        except:
            logger.warning("invalid date %s", date)
            raise cherrypy.HTTPError(400, _("Invalid date."))

        # Get if backup in progress
        if repo_obj.in_progress:
            raise cherrypy.HTTPError(
                500,
                _("""A backup is currently in progress to this repository. Restores are disabled until this backup is complete."""
                  ))

        # Determine the kind.
        kind = kind or 'zip'
        if usetar is not None:
            kind = 'tar.gz'

        # Restore file(s)
        filename, fileobj = path_obj.restore(file_b, int(date), kind=kind)

        # Define content-disposition.
        cherrypy.response.headers[
            "Content-Disposition"] = self._content_disposition(filename)

        # Stream the data.
        return _serve_fileobj(fileobj, content_type=None, content_length=None)
Example #30
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Get user root directory
        filename = None
        user_root = self.app.currentuser.user_root
        if user_root:
            filename = os.path.join(user_root, '.ssh', 'authorized_keys')

        # Handle action
        params = {}
        if 'action' in kwargs:
            try:
                action = kwargs['action']
                if action == 'add':
                    self._handle_add(filename, **kwargs)
                elif action == 'delete':
                    self._handle_delete(filename, **kwargs)
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                _logger.warning("unknown error processing action",
                                exc_info=True)
                params['error'] = _("Unknown error")

        # Get SSH keys if file exists.
        params["sshkeys"] = []
        if filename:
            try:
                params["sshkeys"] = [{
                    'title':
                    key.comment or (key.keytype + ' ' + key.key[:18]),
                    'fingerprint':
                    key.fingerprint,
                    'lineno':
                    key.lineno
                } for key in authorizedkeys.read(filename)]
            except IOError:
                params['error'] = _("error reading SSH keys file")
                _logger.warning("error reading SSH keys file [%s]", filename)
        else:
            params['error'] = _("error reading SSH keys file")
            _logger.warning("SSH keys file [%s] is not accessible", filename)

        return "prefs_sshkeys.html", params
Example #31
0
    def filter_data(self, template_name, data):

        if data.get('repo_path'):
            # Add our graph item in repo_nav_bar
            # id, label, url, icon
            data.setdefault('repo_nav_bar_extras', []).append(
                ('graphs', _('Graphs'),
                 url_for_graphs(data.get('repo_path'),
                                'activities'), 'icon-chart-bar'))
Example #32
0
    def set_password(self, username, password, old_password=None):
        """Update the password of the given user."""
        assert isinstance(username, str)
        assert old_password is None or isinstance(old_password, str)
        assert isinstance(password, str)

        # Do nothing if password is empty
        if not password:
            raise RdiffError(_("Password can't be empty."))
        # Check if users are allowed to change their password in LDAP.
        if not self.allow_password_change:
            raise RdiffError(_("LDAP users are not allowed to change their password."))

        # Check if old_password id valid
        if old_password and not self.are_valid_credentials(username, old_password):
            raise RdiffError(_("Wrong password."))

        # Update the username password of the given user. If possible.
        return self._set_password_in_ldap(username, old_password, password)
Example #33
0
    def user_password_changed(self, username, password):
        """
        Implementation of IUserChangeListener interface.
        """

        # get User object (to get email)
        userobj = self.app.userdb.get_user(username)
        assert userobj
        # If the email attributes was changed, send a mail notification.
        self.send_mail(userobj, _("Password changed"), "password_changed.html")
Example #34
0
    def set_password(self, username, password, old_password=None):
        """Update the password of the given user."""
        assert isinstance(username, unicode)
        assert old_password is None or isinstance(old_password, unicode)
        assert isinstance(password, unicode)

        # Do nothing if password is empty
        if not password:
            raise ValueError(_("password can't be empty"))
        # Check if users are allowed to change their password in LDAP.
        if not self.allow_password_change:
            raise RdiffError(_("LDAP users are not allowed to change their password."))

        # Check if old_password id valid
        if old_password and not self.are_valid_credentials(username, old_password):
            raise ValueError(_("wrong password"))

        # Update the username password of the given user. If possible.
        return self._set_password_in_ldap(username, old_password, password)
Example #35
0
    def _execute(self, username, function):
        assert isinstance(username, str)

        """Reusable method to run LDAP operation."""

        assert self.uri, "LdapUri must be define in configuration"
        assert self.base_dn, "LdapBaseDn must be define in configuration"
        if self.scope == "base":
            scope = ldap.SCOPE_BASE
        elif self.scope == "onelevel":
            scope = ldap.SCOPE_ONELEVEL
        else:
            scope = ldap.SCOPE_SUBTREE

        # try STARTLS if configured
        if self.tls:
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)

        # Check LDAP credential only.
        l = ldap.initialize(self.uri)

        # Set v2 or v3
        if self.version == 2:
            l.protocol_version = ldap.VERSION2
        else:
            l.protocol_version = ldap.VERSION3

        try:
            # Bind to the LDAP server
            logger.debug("binding to ldap server {}".format(self.uri))
            l.simple_bind_s(self.bind_dn, self.bind_password)

            # Search the LDAP server
            search_filter = "(&{}({}={}))".format(
                self.filter, self.attribute, username)
            logger.debug("search ldap server: {}/{}?{}?{}?{}".format(
                self.uri, self.base_dn, self.attribute, scope,
                search_filter))
            r = l.search_s(self.base_dn, scope, search_filter)

            # Execute operation
            return function(l, r)
        except ldap.LDAPError as e:
            l.unbind_s()
            # Handle the LDAP exception and build a nice user message.
            logger.warning('ldap error', exc_info=1)
            msg = _("An LDAP error occurred: %s")
            ldap_msg = str(e)
            if hasattr(e, 'message') and isinstance(e.message, dict):
                if 'desc' in e.message:
                    ldap_msg = e.message['desc']
                if 'info' in e.message:
                    ldap_msg = e.message['info']
            raise RdiffError(msg % ldap_msg)
Example #36
0
 def set_password(self, user, password, old_password=None):
     # Check if user exists in database
     db = self.find_user_database(user)
     if not db:
         raise InvalidUserError(user)
     # Try to update the user password.
     store = self.find_user_store(user)
     if store and not store.supports('set_password'):
         logger.warn(
             "authentication backend for user [%s] does not support changing the password",
             user)
         raise RdiffError(_("You cannot change the user's password."))
     elif not store:
         store = self._get_supporting_store('set_password')
     if not store:
         logger.warn(
             "none of the IPasswordStore supports setting the password")
         raise RdiffError(_("You cannot change the user's password."))
     store.set_password(user, password, old_password)
     self._notify('password_changed', user, password)
Example #37
0
    def _handle_set_password(self, **kwargs):
        """
        Called when changing user password.
        """
        if 'current' not in kwargs or not kwargs['current']:
            raise ValueError(_("current password is missing"))
        if 'new' not in kwargs or not kwargs['new']:
            raise ValueError(_("new password is missing"))
        if 'confirm' not in kwargs or not kwargs['confirm']:
            raise ValueError(_("confirmation password is missing"))

        # Check if confirmation is valid.
        if kwargs['new'] != kwargs['confirm']:
            return {'error': _("The new password and its confirmation does not matches.")}

        # Update user password
        user = self.app.currentuser.username
        _logger.info("updating user [%s] password", user)
        self.app.userdb.set_password(user, kwargs['new'], old_password=kwargs['current'])
        return {'success': _("Password updated successfully.")}
Example #38
0
    def default(self, path=b"", date=None, kind=None, usetar=None):
        self.assertIsInstance(path, bytes)
        self.assertIsInstance(date, str)
        self.assertTrue(kind is None or kind in ARCHIVERS)
        self.assertTrue(usetar is None or isinstance(usetar, str))

        logger.debug("restoring [%r][%s]", path, date)

        # The path wont have leading and trailing "/".
        (path, file_b) = os.path.split(path)
        if not path:
            path = file_b
            file_b = b""

        # Check user access to repo / path.
        (repo_obj, path_obj) = self.validate_user_path(path)

        # Get the restore date
        try:
            rdw_helpers.rdwTime(int(date))
        except:
            logger.warning("invalid date %s", date)
            raise cherrypy.HTTPError(400, _("Invalid date."))

        # Get if backup in progress
        if repo_obj.in_progress:
            raise cherrypy.HTTPError(500, _("""A backup is currently in progress to this repository. Restores are disabled until this backup is complete."""))

        # Determine the kind.
        kind = kind or 'zip'
        if usetar is not None:
            kind = 'tar.gz'

        # Restore file(s)
        filename, fileobj = path_obj.restore(file_b, int(date), kind=kind)

        # Define content-disposition.
        cherrypy.response.headers["Content-Disposition"] = self._content_disposition(filename)

        # Stream the data.
        return _serve_fileobj(fileobj, content_type=None, content_length=None)
Example #39
0
    def render_prefs_panel(self, panelid, **kwargs):  # @UnusedVariable
        # Get user root directory
        filename = None
        user_root = self.app.currentuser.user_root
        if user_root:
            filename = os.path.join(user_root, '.ssh', 'authorized_keys')

        # Handle action
        params = {}
        if 'action' in kwargs:
            try:
                action = kwargs['action']
                if action == 'add':
                    self._handle_add(filename, **kwargs)
                elif action == 'delete':
                    self._handle_delete(filename, **kwargs)
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                _logger.warning("unknown error processing action", exc_info=True)
                params['error'] = _("Unknown error")

        # Get SSH keys if file exists.
        params["sshkeys"] = []
        if filename:
            try:
                params["sshkeys"] = [
                    {'title': key.comment or (key.keytype + ' ' + key.key[:18]),
                     'fingerprint': key.fingerprint,
                     'lineno': key.lineno}
                    for key in authorizedkeys.read(filename)]
            except IOError:
                params['error'] = _("error reading SSH keys file")
                _logger.warning("error reading SSH keys file [%s]", filename)
        else:
            params['error'] = _("error reading SSH keys file")
            _logger.warning("SSH keys file [%s] is not accessible", filename)

        return "prefs_sshkeys.html", params
Example #40
0
        def check_crendential(l, r):
            # Check results
            if len(r) != 1:
                logger.debug("user [%s] not found in LDAP", username)
                return None

            # Bind using the user credentials. Throws an exception in case of
            # error.
            l.simple_bind_s(r[0][0], password)
            try:
                logger.info("user [%s] found in LDAP", username)

                # Verify the shadow expire
                if self.check_shadow_expire:
                    shadow_expire = self._attr_shadow_expire(r)
                    # Convert nb. days into seconds.
                    if shadow_expire and shadow_expire * 24 * 60 * 60 < time.time(
                    ):
                        logger.warn("user account %s expired: %s", username,
                                    shadow_expire)
                        raise RdiffError(
                            _('User account %s expired.' % username))

                # Get username
                dn = r[0][0]
                new_username = self._decode(r[0][1][self.attribute][0])

                # Verify if the user is member of the required group
                if self.require_group:
                    value = dn if self.group_attribute_is_dn else new_username
                    logger.info("check if user [%s] is member of [%s]", value,
                                self.require_group)
                    if not l.compare_s(self.require_group,
                                       self.group_attribute, value):
                        raise RdiffError(
                            _('Permissions denied for user account %s.' %
                              username))
            finally:
                l.unbind_s()
            # Return the username
            return new_username
Example #41
0
 def change_passwd(l, r):
     if len(r) != 1:
         raise ValueError(_("user %s not found)" % (username,)))
     # Bind using the user credentials. Throws an exception in case of
     # error.
     if old_password is not None:
         l.simple_bind_s(r[0][0], encode_s(old_password))
     l.passwd_s(r[0][0], encode_s(old_password), encode_s(password))
     l.unbind_s()
     logger.info("password for user [%s] is updated in LDAP" % username)
     # User updated, return False
     return False
Example #42
0
 def change_passwd(l, r):
     if len(r) != 1:
         raise RdiffError(_("User %s not found." % (username, )))
     # Bind using the user credentials. Throws an exception in case of
     # error.
     if old_password is not None:
         l.simple_bind_s(r[0][0], old_password)
     l.passwd_s(r[0][0], old_password, password)
     l.unbind_s()
     logger.info("password for user [%s] is updated in LDAP", username)
     # User updated, return False
     return False
Example #43
0
    def index(self, path=b"", keepdays=None):
        self.assertIsInstance(path, bytes)
        self.assertTrue(keepdays)
        _logger.debug("repo settings [%r]", path)

        # Get new value
        try:
            keepdays = int(keepdays)
        except:
            _logger.warning("invalid keepdays value %r", keepdays)
            raise cherrypy.HTTPError(400, _("Invalid value"))

        # Check user permissions
        repo_obj = self.validate_user_path(path)[0]

        # Get repository object from user database.
        r = self.app.currentuser.get_repo(repo_obj.path)

        # Update the database.
        r.set_attr(KEEPDAYS, keepdays)

        return _("Updated")
Example #44
0
    def index(self, path=b"", keepdays=None):
        self.assertIsInstance(path, bytes)
        self.assertTrue(keepdays)
        _logger.debug("repo settings [%r]", path)

        # Get new value
        try:
            keepdays = int(keepdays)
        except:
            _logger.warning("invalid keepdays value %r", keepdays)
            raise cherrypy.HTTPError(400, _("Invalid value"))

        # Check user permissions
        repo_obj = self.validate_user_path(path)[0]

        # Get repository object from user database.
        r = self.app.currentuser.get_repo(repo_obj.path)

        # Update the database.
        r.set_attr(KEEPDAYS, keepdays)

        return _("Updated")
Example #45
0
    def user_attr_changed(self, username, attrs={}):
        """
        Implementation of IUserChangeListener interface.
        """
        # Leave if the mail was not changed.
        if 'email' not in attrs:
            return

        # get User object (to get email)
        userobj = self.app.userdb.get_user(username)
        assert userobj
        # If the email attributes was changed, send a mail notification.
        self.send_mail(userobj, _("Email address changed"), "email_changed.html")
Example #46
0
    def status(self):
        """Check if a backup is in progress for the current repo."""
        # Filter the files to keep current_mirror.* files
        current_mirrors = [
            x for x in self._data_entries if x.startswith(b"current_mirror.")
        ]

        pid_re = re.compile(b"^PID\s*([0-9]+)", re.I | re.M)

        def extract_pid(current_mirror):
            """Return process ID from a current mirror marker, if any"""
            entry = IncrementEntry(self, current_mirror)
            match = pid_re.search(entry.read())
            if not match:
                return None
            else:
                return int(match.group(1))

        # Read content of the file and check if pid still exists
        for current_mirror in current_mirrors:
            pid = extract_pid(current_mirror)
            try:
                p = psutil.Process(pid)
                if any('rdiff-backup' in c for c in p.cmdline()):
                    return (
                        'in_progress',
                        _('A backup is currently in progress to this repository.'
                          ))
            except psutil.NoSuchProcess:
                logger.debug('pid [%s] does not exists', pid)
                pass
        # If multiple current_mirror file exists and none of them are associated to a PID, this mean the last backup was interrupted.
        # Also, if the last backup date is undefined, this mean the first initial backup was interrupted.
        if len(current_mirrors) > 1 or not self.last_backup_date:
            return ('interrupted',
                    _('The previous backup seams to have failed.'))

        return ('ok', '')
Example #47
0
    def default(self, path=b"", date=None, kind=None, usetar=None):
        self.assertIsInstance(path, bytes)
        self.assertIsInstance(date, str)
        self.assertTrue(kind is None or kind in ARCHIVERS)
        self.assertTrue(usetar is None or isinstance(usetar, str))

        logger.debug("restoring [%r][%s]", path, date)

        # Check user access to repo / path.
        (repo_obj, path_obj) = self.validate_user_path(path)

        # Get the restore date
        try:
            RdiffTime(int(date))
        except:
            logger.warning("invalid date %s", date)
            raise cherrypy.HTTPError(400, _("Invalid date."))

        # Get if backup in progress
        # status = repo_obj.status
        # if status[0] != 'ok':
        #    raise cherrypy.HTTPError(500, _(status[1] + ' ' + _("""Restores are disabled.""")))

        # Determine the kind.
        kind = kind or 'zip'
        if usetar is not None:
            kind = 'tar.gz'

        # Restore file(s)
        filename, fileobj = path_obj.restore(int(date), kind=kind)

        # Define content-disposition.
        cherrypy.response.headers[
            "Content-Disposition"] = _content_disposition(filename)

        # Set content-type based on filename extension
        content_type = _content_type(filename)
        cherrypy.response.headers['Content-Type'] = content_type

        # Stream the data.
        # Make use of _serve_fileobj() because the fsstat() function on a pipe
        # return a size of 0 for Content-Length. This behavior brake all the flow.
        return _serve_fileobj(fileobj,
                              content_type=content_type,
                              content_length=None)
Example #48
0
    def index(self, path_b=b"", **kwargs):
        assert isinstance(path_b, str)

        _logger.debug("repo settings [%s]", decode_s(path_b, 'replace'))

        # Check user permissions
        try:
            repo_obj = self.validate_user_path(path_b)[0]
        except librdiff.FileError as e:
            _logger.exception("invalid user path [%s]", decode_s(path_b, 'replace'))
            return self._compile_error_template(unicode(e))

        # Check if any action to process.
        params = {}
        action = kwargs.get('action')
        if action:
            try:
                if action == "delete":
                    params.update(self._handle_delete(repo_obj, **kwargs))
                elif action == "set_encoding":
                    params.update(self._handle_set_encoding(repo_obj, **kwargs))
                else:
                    _logger.info("unknown action: %s", action)
                    raise cherrypy.NotFound("Unknown action")
            except ValueError as e:
                params['error'] = unicode(e)
            except HTTPRedirect as e:
                # Re-raise HTTPRedirect exception.
                raise e
            except Exception as e:
                _logger.warn("unknown error processing action", exc_info=True)
                params['error'] = _("Unknown error")

        # Get page data.
        try:
            params.update(self._get_parms_for_page(repo_obj))
        except librdiff.FileError:
            _logger.exception("can't create page params")
            return self._compile_error_template(unicode(e))

        # Generate page.
        return self._compile_template("settings.html", **params)
Example #49
0
    def default(self, path=b"", date=None, kind=None, usetar=None):
        self.assertIsInstance(path, bytes)
        self.assertIsInstance(date, str)
        self.assertTrue(kind is None or kind in ARCHIVERS)
        self.assertTrue(usetar is None or isinstance(usetar, str))

        logger.debug("restoring [%r][%s]", path, date)

        # Check user access to repo / path.
        (repo_obj, path_obj) = self.validate_user_path(path)

        # Get the restore date
        try:
            RdiffTime(int(date))
        except:
            logger.warning("invalid date %s", date)
            raise cherrypy.HTTPError(400, _("Invalid date."))

        # Get if backup in progress
        # status = repo_obj.status
        # if status[0] != 'ok':
        #    raise cherrypy.HTTPError(500, _(status[1] + ' ' + _("""Restores are disabled.""")))

        # Determine the kind.
        kind = kind or 'zip'
        if usetar is not None:
            kind = 'tar.gz'

        # Restore file(s)
        filename, fileobj = path_obj.restore(int(date), kind=kind)

        # Define content-disposition.
        cherrypy.response.headers["Content-Disposition"] = _content_disposition(filename)

        # Set content-type based on filename extension
        content_type = _content_type(filename)
        cherrypy.response.headers['Content-Type'] = content_type

        # Stream the data.
        # Make use of _serve_fileobj() because the fsstat() function on a pipe
        # return a size of 0 for Content-Length. This behavior brake all the flow.
        return _serve_fileobj(fileobj, content_type=content_type, content_length=None)
Example #50
0
    def _handle_delete(self, repo_obj, **kwargs):
        """
        Delete the repository.
        """
        # Validate the name
        confirm_name = kwargs.get('confirm_name')
        if confirm_name != repo_obj.display_name:
            raise ValueError(_("confirmation doesn't matches"))

        # Update the repository encoding
        _logger.info("deleting repository [%s]", repo_obj)
        repo_obj.delete()

        # Refresh repository list
        username = self.app.currentuser.username
        repos = self.app.userdb.get_repos(username)
        repos.remove(b"/" + repo_obj.path)
        self.app.userdb.set_repos(username, repos)

        raise HTTPRedirect("/")
Example #51
0
 def add_user(self, user, password=None):
     """
     Used to add a new user with an optional password.
     """
     assert password is None or isinstance(password, unicode)
     # Check if user already exists.
     db = self.find_user_database(user)
     if db:
         raise ValueError(_("user %s already exists" % (user,)))
     # Find a database where to add the user
     db = self._get_supporting_database('add_user')
     logger.info("adding new user [%s] to database [%s]", user, db)
     db.add_user(user)
     self._notify('added', user, password)
     # Find a password store where to set password
     if password:
         # Check if database support set password, otherwise try to set password as usual.
         if hasattr(db, 'set_password'):
             db.set_password(user, password)
         else:
             self.set_password(user, password)
Example #52
0
    def _get_parms_for_page(self, repo_obj, path_obj, restore, limit):

        # Build "parent directories" links
        # TODO This Should to me elsewhere. It contains logic related to librdiff encoding.
        parents = []
        parents.append({"path": b"", "name": repo_obj.display_name})
        parent_path_b = b""
        for part_b in path_obj.path.split(b'/'):
            if part_b:
                parent_path_b = os.path.join(parent_path_b, part_b)
                display_name = repo_obj._decode(repo_obj.unquote(part_b))
                parents.append({"path": parent_path_b, "name": display_name})

        # Set up warning about in-progress backups, if necessary
        warning = False
        status = repo_obj.status
        if status[0] != 'ok':
            warning = status[1] + ' ' + _(
                "The displayed data may be inconsistent.")

        dir_entries = []
        restore_dates = []
        if restore:
            restore_dates = path_obj.change_dates[:-limit - 1:-1]
        else:
            # Get list of actual directory entries
            dir_entries = path_obj.dir_entries[::-1]

        return {
            "limit": limit,
            "repo_name": repo_obj.display_name,
            "repo_path": repo_obj.path,
            "path": path_obj.path,
            "dir_entries": dir_entries,
            "isdir": path_obj.isdir,
            "parents": parents,
            "restore_dates": restore_dates,
            "warning": warning
        }
Example #53
0
    def _get_parms_for_page(self):
        """
        Build the params for the locations templates.
        """
        # Get user's locations.
        user_root = self.app.currentuser.user_root
        user_repos = self.app.currentuser.repos
        repos = []
        for user_repo in user_repos:
            try:
                # Get reference to a repo object
                repo_obj = librdiff.RdiffRepo(user_root, user_repo)
                path = repo_obj.path
                name = repo_obj.display_name
                status = repo_obj.status
                last_backup_date = repo_obj.last_backup_date
            except librdiff.FileError:
                logger.exception("invalid user path %s" % user_repo)
                path = encodefilename(user_repo.strip('/'))
                name = user_repo.strip('/')
                status = (
                    'failed',
                    _('The repository cannot be found or is badly damaged.'))
                last_backup_date = 0
            # Create an entry to represent the repository
            repos.append({
                "path": path,
                "name_split": name.strip('/').split('/'),
                "last_backup_date": last_backup_date,
                'status': status,
            })
        params = {
            "repos": repos,
            "templates_before_content": list(),
        }

        # Return the complete list of params.
        return params
Example #54
0
        def check_crendential(l, r):
            # Check results
            if len(r) != 1:
                logger.debug("user [%s] not found in LDAP", username)
                return None

            # Bind using the user credentials. Throws an exception in case of
            # error.
            l.simple_bind_s(r[0][0], password)
            l.unbind_s()
            logger.info("user [%s] found in LDAP", username)

            # Verify the shadow expire
            shadow_expire = self._attr_shadow_expire(r)
            if self.check_shadow_expire and shadow_expire:
                # Convert nb. days into seconds.
                shadow_expire = shadow_expire * 24 * 60 * 60
                if shadow_expire < time.time():
                    logger.warn("user account %s expired: %s", username, shadow_expire)
                    raise RdiffError(_('User account %s expired.' % username))

            # Return the username
            return self._decode(r[0][1][self.attribute][0])
Example #55
0
    def users(self,
              userfilter=u"",
              usersearch=u"",
              action=u"",
              username=u"",
              email=u"",
              password=u"",
              user_root=u"",
              is_admin=u""):

        # Check if user is an administrator
        if not self.app.currentuser or not self.app.currentuser.is_admin:
            raise cherrypy.HTTPError(403)

        self.assertIsInstance(userfilter, str)
        self.assertIsInstance(usersearch, str)

        # If we're just showing the initial page, just do that
        params = {}
        if self._is_submit():
            try:
                params = self._users_handle_action(action, username, email,
                                                   password, user_root,
                                                   is_admin)
            except RdiffWarning as e:
                params['warning'] = str(e)
            except RdiffError as e:
                params['error'] = str(e)
            except Exception as e:
                logger.warning("unknown error", exc_info=True)
                params['error'] = _("Unknown error")

        # Get page parameters
        params.update(self._users_get_params_for_page(userfilter, usersearch))

        # Build users page
        return self._compile_template("admin_users.html", **params)