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')
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')
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)
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))
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))
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))
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)
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)
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())
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 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())
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)
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)
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)
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()
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)