Esempio n. 1
0
    def _reset(self):
        """
        Manages submissions to the password reset form.
        """
        log.debug('Form validated successfully')
        try:
            u = meta.session.query(User).filter_by(email=self.form_result['email']).one()
        except:
            log.debug('Invalid email address somehow')
            c.message = _('We do not have an account with that email address')
            return self.index(get=True)

        # If that worked, then we send the user an email with a temporary URL
        # they can use to have our system generate a new password for them.
        log.debug('Sending activation email')

        email = Email('password_reset')
        password_reset_data = PasswordReset.create_for_user(u)
        meta.session.add(password_reset_data)
        meta.session.commit()

        recipient = u.email
        password_reset_url = 'http://' + config['debexpo.sitename'] + url.current(
            action='actually_reset_password', id=password_reset_data.temporary_auth_key)
        email.send([recipient], password_reset_url=password_reset_url)

        # FIXME: This should be a HTTP redirect
        return render('/password_recover/_reset.mako')
Esempio n. 2
0
    def _reset(self):
        """
        Manages submissions to the password reset form.
        """
        log.debug('Form validated successfully')
        try:
            u = meta.session.query(User).filter_by(
                email=self.form_result['email']).one()
        except:
            log.debug('Invalid email address somehow')
            c.message = _('We do not have an account with that email address')
            return self.index(get=True)

        # If that worked, then we send the user an email with a temporary URL
        # they can use to have our system generate a new password for them.
        log.debug('Sending activation email')

        email = Email('password_reset')
        password_reset_data = PasswordReset.create_for_user(u)
        meta.session.add(password_reset_data)
        meta.session.commit()

        recipient = u.email
        password_reset_url = 'http://' + config[
            'debexpo.sitename'] + url.current(
                action='actually_reset_password',
                id=password_reset_data.temporary_auth_key)
        email.send([recipient], password_reset_url=password_reset_url)

        # FIXME: This should be a HTTP redirect
        return render('/password_recover/_reset.mako')
Esempio n. 3
0
    def _fail(self, reason, use_log=True):
        """
        Fail the upload by sending a reason for failure to the log and then remove all
        uploaded files.

        A package is `fail`ed if there is a problem with debexpo, **not** if there's
        something wrong with the package.

        ``reason``
            String of why it failed.

        ``use_log``
            Whether to use the log. This should only be False when actually loading the log fails.
            In this case, the reason is printed to stderr.
        """
        if use_log:
            log.critical(reason)
        else:
            print >> sys.stderr, reason

        self._remove_files()

        if self.user is not None:
            email = Email('importer_fail_maintainer')
            package = self.changes.get('Source', '')

            self.send_email(email, [self.user.email], package=package)

        email = Email('importer_fail_admin')
        self.send_email(email, [pylons.config['debexpo.email']],
                        message=reason)

        sys.exit(1)
Esempio n. 4
0
    def _comment_submit(self, packagename):
        """
        Comment submission.

        ``packagename``
            Package name to look at.
        """
        log.debug("Comment form validation successful")

        if 'user_id' not in session:
            log.debug('Requires authentication')
            session['path_before_login'] = request.path_info
            session.save()
            redirect(url('login'))

        package = self._get_package(packagename)

        status = constants.PACKAGE_COMMENT_STATUS_NOT_UPLOADED

        if self.form_result['status']:
            status = constants.PACKAGE_COMMENT_STATUS_UPLOADED

        comment = PackageComment(
            user_id=session['user_id'],
            package_version_id=self.form_result['package_version'],
            text=self.form_result['text'],
            time=datetime.now(),
            outcome=self.form_result['outcome'],
            status=status)

        meta.session.add(comment)
        meta.session.commit()

        subscribers = meta.session.query(PackageSubscription).filter_by(
            package=packagename).filter(PackageSubscription.level <= constants.
                                        SUBSCRIPTION_LEVEL_COMMENTS).all()

        user = meta.session.query(User).filter_by(id=session['user_id']).one()
        if len(subscribers) > 0:

            email = Email('comment_posted')
            email.send([s.user.email for s in subscribers],
                       package=packagename,
                       comment=self.form_result['text'],
                       user=user)

        version = package = meta.session.query(PackageVersion).filter_by(
            id=self.form_result['package_version']).first()

        data = version.publish_data
        data['author_email'] = user.email
        data['author_name'] = user.name
        data['content'] = comment.text
        data['outcome'] = comment.outcome

        publish(topic="package.comment", msg=data)

        redirect(url('package', packagename=packagename))
Esempio n. 5
0
    def _comment_submit(self, packagename):
        """
        Comment submission.

        ``packagename``
            Package name to look at.
        """
        log.debug("Comment form validation successful")

        if 'user_id' not in session:
            log.debug('Requires authentication')
            session['path_before_login'] = request.path_info
            session.save()
            redirect(url('login'))

        package = self._get_package(packagename)

        status = constants.PACKAGE_COMMENT_STATUS_NOT_UPLOADED

        if self.form_result['status']:
            status = constants.PACKAGE_COMMENT_STATUS_UPLOADED

        comment = PackageComment(user_id=session['user_id'],
            package_version_id=self.form_result['package_version'],
            text=self.form_result['text'],
            time=datetime.now(),
            outcome=self.form_result['outcome'],
            status=status)

        meta.session.add(comment)
        meta.session.commit()

        subscribers = meta.session.query(PackageSubscription).filter_by(
            package=packagename).filter(
            PackageSubscription.level <= constants.SUBSCRIPTION_LEVEL_COMMENTS).all()

        user = meta.session.query(User).filter_by(id=session['user_id']).one()
        if len(subscribers) > 0:

            email = Email('comment_posted')
            email.send([s.user.email for s in subscribers], package=packagename,
                comment=self.form_result['text'], user=user)

        version = package = meta.session.query(PackageVersion).filter_by(id=self.form_result['package_version']).first()

        data = version.publish_data
        data['author_email'] = user.email
        data['author_name'] = user.name
        data['content'] = comment.text
        data['outcome'] = comment.outcome

        publish(topic="package.comment", msg=data)

        redirect(url('package', packagename=packagename))
Esempio n. 6
0
    def _comment_submit(self, packagename):
        """
        Comment submission.

        ``packagename``
            Package name to look at.
        """
        log.debug("Comment form validation successful")

        if "user_id" not in session:
            log.debug("Requires authentication")
            session["path_before_login"] = request.path_info
            session.save()
            redirect(url("login"))

        package = self._get_package(packagename)

        status = constants.PACKAGE_COMMENT_STATUS_NOT_UPLOADED

        if self.form_result["status"]:
            status = constants.PACKAGE_COMMENT_STATUS_UPLOADED

        comment = PackageComment(
            user_id=session["user_id"],
            package_version_id=self.form_result["package_version"],
            text=self.form_result["text"],
            time=datetime.now(),
            outcome=self.form_result["outcome"],
            status=status,
        )

        meta.session.add(comment)
        meta.session.commit()

        subscribers = (
            meta.session.query(PackageSubscription)
            .filter_by(package=packagename)
            .filter(PackageSubscription.level <= constants.SUBSCRIPTION_LEVEL_COMMENTS)
            .all()
        )

        if len(subscribers) > 0:
            user = meta.session.query(User).filter_by(id=session["user_id"]).one()

            email = Email("comment_posted")
            email.send(
                [s.user.email for s in subscribers], package=packagename, comment=self.form_result["text"], user=user
            )

        redirect(url("package", packagename=packagename))
Esempio n. 7
0
    def _send_activate_email(self, key, recipient):
        """
        Sends an activation email to the potential new user.

        ``key``
            Activation key that's already stored in the database.

        ``recipient``
            Email address to send to.
        """
        log.debug('Sending activation email')
        email = Email('register_activate')
        url = 'http://' + request.host + h.url_for(action='activate', id=key)
        email.send([recipient], activate_url=url)
Esempio n. 8
0
    def _send_activate_email(self, key, recipient):
        """
        Sends an activation email to the potential new user.

        ``key``
            Activation key that's already stored in the database.

        ``recipient``
            Email address to send to.
        """
        log.debug('Sending activation email')
        email = Email('register_activate')
        activate_url = 'http://' + config['debexpo.sitename'] + url.current(action='activate', id=key)
        email.send([recipient], activate_url=activate_url)
Esempio n. 9
0
    def test_send_mail(self):
        """
        Send mail to changes list.
        """
        log.debug('Sending mail to changes list')

        if not pylons.config.get('debexpo.changes_list', None):
            return

        if pylons.config['debexpo.changes_list'] == '':
            return

        email = Email('changes_list')
        to = pylons.config['debexpo.changes_list']
        email.send([to], changes=self.changes,
                changes_contents=self.changes_contents.decode('ascii', 'ignore'),
                dest=self.changes.get_pool_path())
Esempio n. 10
0
 def setup(self):
     self.mailer = Email('upload_removed_from_expo')
     self.mailer.connect_to_server()
     self.pkg_controller = PackageController()
     self.pkgs_controller = PackagesController()
     apt_pkg.init_system()
     self.last_cruft_run = datetime.datetime(year=1970, month=1, day=1)
     self.log.debug("%s loaded successfully" % (__name__))
Esempio n. 11
0
    def test_send_mail(self):
        """
        Send mail to changes list.
        """
        log.debug('Sending mail to changes list')

        if not config.get('debexpo.changes_list', None):
            return

        if config['debexpo.changes_list'] == '':
            return

        email = Email('changes_list')
        to = config['debexpo.changes_list']
        email.send([to], changes=self.changes,
                changes_contents=self.changes_contents.decode('ascii', 'ignore'),
                dest=self.changes.get_pool_path())
Esempio n. 12
0
    def comment(self, packagename):
        """
        Comment submission.

        ``packagename``
            Package name to look at.
        """
        package = self._get_package(packagename)
        if not isinstance(package, Package):
            return package

        status = constants.PACKAGE_COMMENT_STATUS_NOT_UPLOADED
        if "status" in request.POST and request.POST["status"]:
            status = constants.PACKAGE_COMMENT_STATUS_UPLOADED

        comment = PackageComment(
            user_id=session["user_id"],
            package_version_id=request.POST["package_version"],
            text=request.POST["text"],
            time=datetime.now(),
            outcome=request.POST["outcome"],
            status=status,
        )

        meta.session.save(comment)
        meta.session.commit()

        subscribers = (
            meta.session.query(PackageSubscription)
            .filter_by(package=packagename)
            .filter(PackageSubscription.level <= constants.SUBSCRIPTION_LEVEL_COMMENTS)
            .all()
        )

        if len(subscribers) > 0:
            user = meta.session.query(User).filter_by(id=session["user_id"]).one()

            email = Email("comment_posted")
            email.send(
                [s.user.email for s in subscribers], package=packagename, comment=request.POST["text"], user=user
            )

        return h.rails.redirect_to("package", packagename=packagename)
Esempio n. 13
0
    def comment(self, packagename):
        """
        Comment submission.

        ``packagename``
            Package name to look at.
        """
        package = self._get_package(packagename)
        if not isinstance(package, Package):
            return package

        status = constants.PACKAGE_COMMENT_STATUS_NOT_UPLOADED
        if 'status' in request.POST and request.POST['status']:
            status = constants.PACKAGE_COMMENT_STATUS_UPLOADED

        comment = PackageComment(
            user_id=session['user_id'],
            package_version_id=request.POST['package_version'],
            text=request.POST['text'],
            time=datetime.now(),
            outcome=request.POST['outcome'],
            status=status)

        meta.session.save(comment)
        meta.session.commit()

        subscribers = meta.session.query(PackageSubscription).filter_by(package=packagename).filter(\
            PackageSubscription.level <= constants.SUBSCRIPTION_LEVEL_COMMENTS).all()

        if len(subscribers) > 0:
            user = meta.session.query(User).filter_by(
                id=session['user_id']).one()

            email = Email('comment_posted')
            email.send([s.user.email for s in subscribers],
                       package=packagename,
                       comment=request.POST['text'],
                       user=user)

        return h.rails.redirect_to('package', packagename=packagename)
Esempio n. 14
0
    def _reject(self, reason):
        """
        Reject the package by sending a reason for failure to the log and then remove all
        uploaded files.

        A package is `reject`ed if there is a problem with the package.

        ``reason``
            String of why it failed.
        """
        log.error('Rejected: %s' % reason)

        self._remove_changes()
        self._remove_files()

        if self.user is not None:
            email = Email('importer_reject_maintainer')
            package = self.changes.get('Source', '')

            self.send_email(email, [self.user.email],
                            package=package,
                            message=reason)
        sys.exit(1)
Esempio n. 15
0
class RemoveOldUploads(BaseCronjob):

    def _remove_package(self, package, version, reason):
        user = meta.session.query(User).filter_by(id=package.user_id).one()
        if user:
            self.mailer.send([user.email, ],
                package=package.name,
                version=version,
                reason=reason)

        CheckFiles().delete_files_for_package(package)
        meta.session.delete(package)
        meta.session.commit()

    def _process_changes(self, mail):
        if mail.is_multipart():
            self.log.debug("Changes message is multipart?!")
            return
        changes = mail.get_payload(decode=True)
        try:
            changes = deb822.Changes(changes)
        except:
            self.log.error('Could not open changes file; skipping mail "%s"' % (mail['subject']))
            return

        if not 'Source' in changes:
            #self.log.debug('Changes file "%s" seems incomplete' % (mail['subject']))
            return
        package = self.pkg_controller._get_package(changes['Source'], from_controller=False)
        if package != None:
            for pv in package.package_versions:
                if pv.distribution == changes['Distribution'] and apt_pkg.version_compare(changes['Version'], pv.version) == 0:
                    self.log.debug("Package %s was was uploaded to Debian - removing it from Expo" % (changes['Source']))
                    self._remove_package(package, pv.version, "Package was uploaded to official Debian repositories")
        else:
            #self.log.debug("Package %s was not uploaded to Expo before - ignoring it" % (changes['Source']))
            pass

    def _remove_uploaded_packages(self):

        if self.mailer.connection_established():
            lists = meta.session.query(DataStore).filter(DataStore.namespace == __namespace__).all()
            for list_name in lists:
                for message in self.mailer.unread_messages(list_name.code, list_name.value):
                    self._process_changes(message)
                    list_name.value = message['X-Debexpo-Message-Number']
                self.log.debug("Processed all messages up to #%s on %s" % (list_name.value, list_name.code))
                meta.session.merge(list_name)
            meta.session.commit()
            self.mailer.disconnect_from_server()

    def _remove_old_packages(self):
        now = datetime.datetime.now()
        for package in self.pkgs_controller._get_packages():
            if (now - package.package_versions[-1].uploaded) > datetime.timedelta(weeks = 20):
                self.log.debug("Removing package %s - uploaded on %s" % (package.name, package.package_versions[-1].uploaded))
                self._remove_package(package, "all versions", "Your package found no sponsor for 20 weeks")

    def setup(self):
        self.mailer = Email('upload_removed_from_expo')
        self.mailer.connect_to_server()
        self.pkg_controller = PackageController()
        self.pkgs_controller = PackagesController()
        apt_pkg.init_system()
        self.last_cruft_run = datetime.datetime(year=1970, month=1, day=1)
        self.log.debug("%s loaded successfully" % (__name__))



    def teardown(self):
        self.mailer.disconnect_from_server()

    def invoke(self):
        try:
            self._remove_uploaded_packages()
        except socket.error as e:
            # better luck next time
            self.log.debug("Socket error %s: skipping removals his time" % (e))
            pass

        # We don't need to run our garbage collection of old cruft that often
        # It's ok if we purge old packages once a day.
        if (datetime.datetime.now() - self.last_cruft_run) >= datetime.timedelta(hours = 24):
            self.last_cruft_run = datetime.datetime.now()
            self._remove_old_packages()
Esempio n. 16
0
    def _create_db_entries(self, qa):
        """
        Create entries in the Database for the package upload.
        """
        def _package_description(raw):
            return raw[2:].replace('      - ', ' - ')

        log.debug('Creating database entries')

        # Parse component and section from field in changes
        component, section = parse_section(self.changes['files'][0]['section'])

        # Check whether package is already in the database
        package_query = meta.session.query(Package).filter_by(
            name=self.changes['Source'])
        if package_query.count() == 1:
            log.debug('Package %s already exists in the database' %
                      self.changes['Source'])
            package = package_query.one()
            # Update description to make sure it reflects the latest upload
            package.description = _package_description(
                self.changes['Description'])
        else:
            log.debug('Package %s is new to the system' %
                      self.changes['Source'])
            package = Package(name=self.changes['Source'], user=self.user)
            package.description = _package_description(
                self.changes['Description'])
            package.needs_sponsor = 0
            meta.session.add(package)

        # No need to check whether there is the same source name and same version as an existing
        # entry in the database as the upload controller tested whether similar filenames existed
        # in the repository. The only way this would be wrong is if the filename had a different
        # version in than the Version field in changes..

        try:
            closes = self.changes['Closes']
        except KeyError:
            closes = None

        # TODO: fix these magic numbers
        if qa.stop():
            qa_status = 1
        else:
            qa_status = 0

        maintainer_matches = re.compile(r'(.*) <(.*)>').match(
            self.changes['Changed-By'])
        maintainer = maintainer_matches.group(2)

        package_version = PackageVersion(
            package=package,
            version=self.changes['Version'],
            section=section,
            distribution=self.changes['Distribution'],
            qa_status=qa_status,
            component=component,
            priority=self.changes.get_priority(),
            closes=closes,
            uploaded=datetime.now(),
            maintainer=maintainer)
        meta.session.add(package_version)

        source_package = SourcePackage(package_version=package_version)
        meta.session.add(source_package)

        binary_package = None

        # Add PackageFile objects to the database for each uploaded file
        for file in self.files:
            filename = os.path.join(self.changes.get_pool_path(), file)
            # This exception should be never caught.
            # It implies something went wrong before, as we expect a file which does not exist
            try:
                sum = md5sum(
                    os.path.join(pylons.config['debexpo.repository'],
                                 filename))
            except AttributeError as e:
                self._fail("Could not calculate MD5 sum: %s" % (e))

            size = os.stat(
                os.path.join(pylons.config['debexpo.repository'],
                             filename))[ST_SIZE]

            # Check for binary or source package file
            if file.endswith('.deb'):
                # Only create a BinaryPackage if there actually binary package files
                if binary_package is None:
                    binary_package = BinaryPackage(
                        package_version=package_version,
                        arch=file[:-4].split('_')[-1])
                    meta.session.add(binary_package)

                meta.session.add(
                    PackageFile(filename=filename,
                                binary_package=binary_package,
                                size=size,
                                md5sum=sum))
            else:
                meta.session.add(
                    PackageFile(filename=filename,
                                source_package=source_package,
                                size=size,
                                md5sum=sum))

        meta.session.commit()
        log.warning("Finished adding PackageFile objects.")

        # Add PackageInfo objects to the database for the package_version
        for result in qa.result:
            meta.session.add(
                PackageInfo(package_version=package_version,
                            from_plugin=result.from_plugin,
                            outcome=result.outcome,
                            rich_data=result.data,
                            severity=result.severity))

        # Commit all changes to the database
        meta.session.commit()
        log.debug('Committed package data to the database')

        subscribers = meta.session.query(PackageSubscription).filter_by(package=self.changes['Source']).filter(\
            PackageSubscription.level <= constants.SUBSCRIPTION_LEVEL_UPLOADS).all()

        if len(subscribers) > 0:
            email = Email('package_uploaded')
            self.send_email(email, [s.user.email for s in subscribers],
                            package=self.changes['Source'],
                            version=self.changes['Version'],
                            user=self.user)

            log.debug('Sent out package subscription emails')

        # Send success email to uploader
        email = Email('successful_upload')
        dsc_url = pylons.config[
            'debexpo.server'] + '/debian/' + self.changes.get_pool_path(
            ) + '/' + self.changes.get_dsc()
        rfs_url = pylons.config['debexpo.server'] + url(
            'rfs', packagename=self.changes['Source'])
        self.send_email(email, [self.user.email],
                        package=self.changes['Source'],
                        dsc_url=dsc_url,
                        rfs_url=rfs_url)