def save_edit(self, builds, notes, expiration=None, **kw): log.debug(repr(locals())) if len(builds) > 1: flash("Unable to add builds to an existing override") raise redirect("/override") builds = builds[0] if expiration: if datetime.utcnow() > expiration: flash("Cannot set an expiration in the past") if request_format() == "json": return dict() raise redirect("/override/edit?build=" + builds) try: override = BuildRootOverride.byBuild(builds) except SQLObjectNotFound: flash("Cannot find override to edit %r" % builds) raise redirect("/override") override.notes = notes override.expiration = expiration if override.date_expired: log.debug("Retagging expired override: %s" % override.build) override.date_expired = None override.tag() flash("%s successfully edited" % builds) if request_format() == "json": return override.__json__() raise redirect("/override")
def save_edit(self, builds, notes, expiration=None, **kw): log.debug(repr(locals())) if len(builds) > 1: flash('Unable to add builds to an existing override') raise redirect('/override') builds = builds[0] if expiration: if datetime.utcnow() > expiration: flash('Cannot set an expiration in the past') if request_format() == 'json': return dict() raise redirect('/override/edit?build=' + builds) try: override = BuildRootOverride.byBuild(builds) except SQLObjectNotFound: flash('Cannot find override to edit %r' % builds) raise redirect('/override') override.notes = notes override.expiration = expiration if override.date_expired: log.debug('Retagging expired override: %s' % override.build) override.date_expired = None override.tag() flash('%s successfully edited' % builds) if request_format() == 'json': return override.__json__() raise redirect('/override')
def login(self, forward_url=None, *args, **kwargs): '''Page to become authenticated to the Account System. This shows a small login box to type in your username and password from the Fedora Account System. :kwarg forward_url: The url to send to once authentication succeeds ''' login_dict = f_ctrlers.login(forward_url=forward_url, *args, **kwargs) if not identity.current.anonymous and identity.was_login_attempted() \ and not identity.get_identity_errors(): # Success that needs to be passed back via json return login_dict if identity.was_login_attempted() and request.fas_provided_username: if request.fas_identity_failure_reason == 'status_inactive': turbogears.flash(_('Your old password has expired. Please' ' reset your password below.')) if request_format() != 'json': redirect('/user/resetpass') if request.fas_identity_failure_reason == 'status_account_disabled': turbogears.flash(_('Your account is currently disabled. For' ' more information, please contact %(admin_email)s' % {'admin_email': config.get('accounts_email')})) if request_format() != 'json': redirect('/login') return login_dict
def login(self, forward_url=None, *args, **kwargs): '''Page to become authenticated to the Account System. This shows a small login box to type in your username and password from the Fedora Account System. :kwarg forward_url: The url to send to once authentication succeeds ''' login_dict = f_ctrlers.login(forward_url=forward_url, *args, **kwargs) if not identity.current.anonymous and identity.was_login_attempted() \ and not identity.get_identity_errors(): # Success that needs to be passed back via json return login_dict if identity.was_login_attempted() and request.fas_provided_username: if request.fas_identity_failure_reason == 'status_inactive': turbogears.flash( _('Your old password has expired. Please' ' reset your password below.')) if request_format() != 'json': redirect('/user/resetpass') if request.fas_identity_failure_reason == 'status_account_disabled': turbogears.flash( _('Your account is currently disabled. For' ' more information, please contact %(admin_email)s' % {'admin_email': config.get('accounts_email')})) if request_format() != 'json': redirect('/login') return login_dict
def list(self, build=None, tg_errors=None, mine=False, release=None, show_expired=False, **kw): query = [] title = '%d Buildroot Overrides' if mine: query.append( BuildRootOverride.q.submitter == identity.current.user_name) title += ' submitted by %s' % identity.current.user_name if release: rel = Release.byName(release) query.append(BuildRootOverride.q.releaseID == rel.id) title += ' for %s' % rel.long_name if not show_expired: query.append(BuildRootOverride.q.date_expired == None) overrides = BuildRootOverride.select(AND(*query)) if request_format() == 'json': overrides = [o.__json__() for o in overrides] num_items = len(overrides) else: num_items = overrides.count() return dict(overrides=overrides, title=title % num_items, num_items=num_items, show_expired=show_expired, mine=mine)
def list(self, build=None, tg_errors=None, mine=False, release=None, show_expired=False, **kw): query = [] title = '%d Buildroot Overrides' if mine: show_expired = True query.append( BuildRootOverride.q.submitter == identity.current.user_name) title += ' submitted by %s' % identity.current.user_name if release: rel = Release.byName(release) query.append( BuildRootOverride.q.releaseID == rel.id) title += ' for %s' % rel.long_name if not show_expired: query.append( BuildRootOverride.q.date_expired == None) overrides = BuildRootOverride.select(AND(*query)) if request_format() == 'json': overrides = [o.__json__() for o in overrides] num_items = len(overrides) else: num_items = overrides.count() return dict(overrides=overrides, title=title % num_items, num_items=num_items, show_expired=show_expired, mine=mine)
def index(self, release=None): # /updates/metrics?tg_format=json API if request_format() == 'json': json = {} query = release and [Release.byName(release)] or Release.select() for release in query: json[release.name] = release.metrics return json try: if not release: rel = Release.select()[0] release = rel.name else: rel = Release.byName(release) except SQLObjectNotFound: flash("Unknown Release") raise redirect('/metrics') widgets = MetricData().get_widgets(release) if not widgets: return dict(metrics=[], title="Metrics currently unavailable") return dict(metrics=[ widgets[name.__name__] for name in metrics if name.__name__ in widgets ], title="%s Update Metrics" % rel.long_name)
def index(self, release=None): # /updates/metrics?tg_format=json API if request_format() == "json": json = {} query = release and [Release.byName(release)] or Release.select() for release in query: json[release.name] = release.metrics return json try: if not release: rel = Release.select()[0] release = rel.name else: rel = Release.byName(release) except SQLObjectNotFound: flash("Unknown Release") raise redirect("/metrics") widgets = MetricData().get_widgets(release) if not widgets: return dict(metrics=[], title="Metrics currently unavailable") return dict( metrics=[widgets[name.__name__] for name in metrics if name.__name__ in widgets], title="%s Update Metrics" % rel.long_name, )
def index(self): if turbogears.identity.not_anonymous(): if request_format() == 'json': # redirects don't work with JSON calls. This is a bit of a # hack until we can figure out something better. return dict() turbogears.redirect('/home') return dict(now=time.ctime())
def save(self, builds, notes, expiration=None, *args, **kw): log.debug(repr(locals())) last_release = None # for our koji wait-repo example if expiration: if datetime.utcnow() > expiration: flash('Cannot set an expiration in the past') if request_format() == 'json': return dict() raise redirect('/override/new') try: koji = get_session() except Exception, e: flash('Unable to connect to Koji') if request_format() == 'json': return dict() raise redirect('/override/new')
def json_redirect(f, *args, **kw): try: return f(*args, **kw) except InvalidUpdateException, e: if request_format() == 'json': return dict() else: raise redirect('/new', **e.args[0])
def error(self, tg_errors=None): '''Show a friendly error message''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 ### FIXME: This can be made simpler once we have a new python-fedora # with jsonify_validation_errors() if tg_errors: if request_format() == 'json': message = '\n'.join([u'%s: %s' % (param, msg) for param, msg in tg_errors.items()]) return dict(exc='Invalid', tg_flash=message, tg_template='json') if not tg_errors: # We should only reach this if the user hit the url manually. if request_format() == 'json': return dict() else: redirect('/') return dict(tg_errors=tg_errors)
def expire(self, build, *args, **kw): """ Expire a given override """ override = BuildRootOverride.byBuild(build) if identity.current.user_name != override.submitter and "releng" not in identity.current.groups: flash("Only the submitter or a releng memeber can " + "expire this buildroot override") if request_format() == "json": return dict() raise redirect("/override") if override.date_expired: flash("Override %s already expired!" % build) if request_format() == "json": return dict() raise redirect("/override") override.date_expired = datetime.utcnow() try: override.untag() except Exception, e: log.error(str(e)) flash(str(e)) raise redirect("/override")
def expire(self, build, *args, **kw): """ Expire a given override """ override = BuildRootOverride.byBuild(build) if identity.current.user_name != override.submitter and \ 'releng' not in identity.current.groups: flash('Only the submitter or a releng memeber can ' + 'expire this buildroot override') if request_format() == 'json': return dict() raise redirect('/override') if override.date_expired: flash('Override %s already expired!' % build) if request_format() == 'json': return dict() raise redirect('/override') override.date_expired = datetime.utcnow() try: override.untag() except Exception, e: log.error(str(e)) flash(str(e)) raise redirect('/override')
def save_edit_cli(self, builds, notes, expiration=None, **kw): log.debug(repr(locals())) if expiration: if datetime.utcnow() > expiration: flash('Cannot set an expiration in the past') if request_format() == 'json': return dict() raise redirect('/override/edit?build=' + builds) try: override = BuildRootOverride.byBuild(builds) except SQLObjectNotFound: flash('Cannot find override to edit %r' % builds) raise redirect('/override') override.notes = notes override.expiration = expiration if override.date_expired: log.debug('Retagging expired override: %s' % override.build) override.date_expired = None override.tag() flash('%s successfully edited' % builds) if request_format() == 'json': return override.__json__() raise redirect('/override')
def expire(self, build, *args, **kw): """ Expire a given override """ override = BuildRootOverride.byBuild(build) if override.date_expired: flash('Override %s already expired!' % build) if request_format() == 'json': return dict() raise redirect('/override') override.date_expired = datetime.utcnow() try: override.untag() except Exception, e: log.error(str(e)) flash(str(e)) raise redirect('/override')
def login(forward_url=None, *args, **kwargs): '''Page to become authenticated to the Account System. This shows a small login box to type in your username and password from the Fedora Account System. To use this, replace your current login controller method with:: from fedora.controllers import login as fc_login @expose(template='yourapp.yourlogintemplate', allow_json=True) def login(self, forward_url=None, *args, **kwargs): login_dict = fc_login(forward_url, args, kwargs) # Add anything to the return dict that you need for your app return login_dict :kwarg: forward_url: The url to send to once authentication succeeds ''' if forward_url: if isinstance(forward_url, list): forward_url = forward_url.pop(0) else: del request.params['forward_url'] if not identity.current.anonymous and identity.was_login_attempted() \ and not identity.get_identity_errors(): # User is logged in flash(_('Welcome, %s') % identity.current.user_name) if request_format() == 'json': # When called as a json method, doesn't make any sense to redirect # to a page. Returning the logged in identity is better. return dict(user=identity.current.user, _csrf_token=identity.current.csrf_token) redirect(forward_url or '/') if identity.was_login_attempted(): msg = _('The credentials you supplied were not correct or ' 'did not grant access to this resource.') elif identity.get_identity_errors(): msg = _('You must provide your credentials before accessing ' 'this resource.') else: msg = _('Please log in.') if not forward_url: forward_url = request.headers.get('Referer', '/') response.status = 403 return dict(logging_in=True, message=msg, forward_url=forward_url, previous_url=request.path_info, original_parameters=request.params)
def error(self, tg_errors=None): '''Show a friendly error message''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 ### FIXME: This can be made simpler once we have a new python-fedora # with jsonify_validation_errors() if tg_errors: if request_format() == 'json': message = '\n'.join([ u'%s: %s' % (param, msg) for param, msg in tg_errors.items() ]) return dict(exc='Invalid', tg_flash=message, tg_template='json') if not tg_errors: # We should only reach this if the user hit the url manually. if request_format() == 'json': return dict() else: redirect('/') return dict(tg_errors=tg_errors)
def set(self, username, application, attribute, value=None): '''Retrieve configs for a user and application. Arguments: :username: owner of the configs we're searching for :application: program that the configs are for :attribute: name of the option we're setting :value: value to set in the db. If ths is None, we won't set anything ''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 # Verify user is allowed to set this config target = People.by_username(username) if not can_edit_user(identity.current.user, target): flash(_('You cannot edit configs for %s') % username) if request_format() == 'json': return dict(exc='AuthorizationError') else: redirect('/') # Retrieve the data and reformat it as a dict keyed on attribute try: # pylint: disable-msg=E1101 config = Configs.query.filter_by( application=application, attribute=attribute).filter(People.username == username).one() config.value = value except InvalidRequestError: # There was no Config, create a new one config = Configs(application=application, attribute=attribute, value=value) # pylint: disable-msg=E1101 config.person = People.query.filter_by(username=username).one() try: # ScopedSession really does have a flush() method # pylint: disable-msg=E1101 session.flush() except SQLError, error: flash(_('Error saving the config to the database: %s' % (error))) return dict(exc='SQLError')
def set(self, username, application, attribute, value=None): '''Retrieve configs for a user and application. Arguments: :username: owner of the configs we're searching for :application: program that the configs are for :attribute: name of the option we're setting :value: value to set in the db. If ths is None, we won't set anything ''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 # Verify user is allowed to set this config target = People.by_username(username) if not can_edit_user(identity.current.user, target): flash(_('You cannot edit configs for %s') % username) if request_format() == 'json': return dict(exc='AuthorizationError') else: redirect('/') # Retrieve the data and reformat it as a dict keyed on attribute try: # pylint: disable-msg=E1101 config = Configs.query.filter_by(application=application, attribute=attribute).filter(People.username==username).one() config.value = value except InvalidRequestError: # There was no Config, create a new one config = Configs(application=application, attribute=attribute, value=value) # pylint: disable-msg=E1101 config.person = People.query.filter_by(username=username).one() try: # ScopedSession really does have a flush() method # pylint: disable-msg=E1101 session.flush() except SQLError, error: flash(_('Error saving the config to the database: %s' % (error))) return dict(exc='SQLError')
def list(self, username, application, pattern=u'*'): '''Retrieve configs for a user and application. Arguments: :username: owner of the configs we're searching for :application: program that the configs are for :pattern: Limit the configs to ones which match this pattern. '*' is a wildcard character Returns: dict that maps the name of the config attribute to the config value. ''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 # Verify user is allowed to view this config target = People.by_username(username) if not can_edit_user(identity.current.user, target): flash(_('You cannot look at configs for %s') % username) if request_format() == 'json': return dict(exc='AuthorizationError') else: redirect('/') # This only works if pattern is unicode. But it should be unicode # because of the validator. pattern = pattern.translate({ord(u'*'): ur'%'}).lower() # Retrieve the data and reformat it as a dict keyed on attribute # pylint: disable-msg=E1101 cfgs = Configs.query.filter_by(application=application).filter( and_(Configs.attribute.like(pattern), People.username == username)) # pylint: enable-msg=E1101 results = dict((cfg.attribute, cfg.value) for cfg in cfgs.all()) return dict(username=username, application=application, pattern=pattern, configs=results)
def list(self, username, application, pattern=u'*'): '''Retrieve configs for a user and application. Arguments: :username: owner of the configs we're searching for :application: program that the configs are for :pattern: Limit the configs to ones which match this pattern. '*' is a wildcard character Returns: dict that maps the name of the config attribute to the config value. ''' # Only tg controller methods are served via the web so we have to have # methods even if they could be functions. (R0201) # pylint: disable-msg=R0201 # Verify user is allowed to view this config target = People.by_username(username) if not can_edit_user(identity.current.user, target): flash(_('You cannot look at configs for %s') % username) if request_format() == 'json': return dict(exc='AuthorizationError') else: redirect('/') # This only works if pattern is unicode. But it should be unicode # because of the validator. pattern = pattern.translate({ord(u'*'): ur'%'}).lower() # Retrieve the data and reformat it as a dict keyed on attribute # pylint: disable-msg=E1101 cfgs = Configs.query.filter_by(application=application).filter( and_(Configs.attribute.like(pattern), People.username==username)) # pylint: enable-msg=E1101 results = dict((cfg.attribute, cfg.value) for cfg in cfgs.all()) return dict(username=username, application=application, pattern=pattern, configs=results)
def logout(url=None): '''Logout from the server. To use this, replace your current login controller method with:: from fedora.controllers import logout as fc_logout @expose(allow_json=True) def logout(self): return fc_logout() :kwarg url: If provided, when the user logs out, they will always be taken to this url. This defaults to taking the user to the URL they were at when they clicked logout. ''' identity.current.logout() flash(_('You have successfully logged out.')) if request_format() == 'json': return dict() if not url: url = request.headers.get('Referer','/') redirect(url)
def mash(self, updates=None, resume=False, **kw): """ Mash a list of PackageUpdate objects. If this instance is deployed with a remote masher, then it simply proxies the request. If we are the masher, then send these updates to our Mash instance. This will then start a thread that takes care of handling all of the update requests, composing fresh repositories, generating and sending update notices, closing bugs, etc. """ if not updates: updates = [] if not isinstance(updates, list): if isinstance(updates, basestring): log.debug("Doing json hack") try: updates = json.loads( updates.replace("u'", "\"").replace("'", "\"")) except: log.debug("Didn't work, assuming it's a single update...") updates = [updates] else: updates = [updates] # If we're not The Masher, then proxy this request to it if config.get('masher'): data = self._masher_request( '/admin/mash', updates=updates, resume=resume) or {} flash_log('Push request %s' % (data.get('success') and 'succeeded' or 'failed')) raise redirect('/admin/masher') from bodhi.masher import masher masher.queue([PackageUpdate.byTitle(title) for title in updates], resume=resume) if request_format() == 'json': return dict(success=True) flash("Updates queued for mashing") raise redirect('/admin/masher')
def mash(self, updates=None, resume=False, **kw): """ Mash a list of PackageUpdate objects. If this instance is deployed with a remote masher, then it simply proxies the request. If we are the masher, then send these updates to our Mash instance. This will then start a thread that takes care of handling all of the update requests, composing fresh repositories, generating and sending update notices, closing bugs, etc. """ if not updates: updates = [] if not isinstance(updates, list): if isinstance(updates, basestring): log.debug("Doing json hack") try: updates = json.loads(updates.replace("u'", "\"").replace("'", "\"")) except: log.debug("Didn't work, assuming it's a single update...") updates = [updates] else: updates = [updates] # If we're not The Masher, then proxy this request to it if config.get('masher'): data = self._masher_request('/admin/mash', updates=updates, resume=resume) or {} flash_log('Push request %s' % (data.get('success') and 'succeeded' or 'failed')) raise redirect('/admin/masher') from bodhi.masher import masher masher.queue([PackageUpdate.byTitle(title) for title in updates], resume=resume) if request_format() == 'json': return dict(success=True) flash("Updates queued for mashing") raise redirect('/admin/masher')
class CLA(controllers.Controller): ''' Processes CLA workflow ''' # Group name for people having signed the CLA CLAGROUPNAME = config.get('cla_standard_group') # Meta group for everyone who has satisfied the requirements of the CLA # (By signing or having a corporate signatue or, etc) CLAMETAGROUPNAME = config.get('cla_done_group') # Values legal in phone numbers PHONEDIGITS = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', ')', '(', ' ') def __init__(self): '''Create a CLA Controller.''' @identity.require(turbogears.identity.not_anonymous()) @expose(template="fas.templates.cla.index") def index(self): '''Display the CLAs (and accept/do not accept buttons)''' show = {} show['show_postal_address'] = config.get('show_postal_address') username = turbogears.identity.current.user_name person = People.by_username(username) try: code_len = len(person.country_code) except TypeError: code_len = 0 if show['show_postal_address']: contactInfo = person.telephone or person.postal_address if person.country_code == 'O1' and not person.telephone: turbogears.flash(_('A telephone number is required to ' + \ 'complete the CLA. Please fill out below.')) elif not person.country_code or not person.human_name \ or not contactInfo: turbogears.flash(_('A valid country and telephone number ' + \ 'or postal address is required to complete the CLA. ' + \ 'Please fill them out below.')) else: if not person.telephone or code_len != 2 or \ person.country_code == ' ': turbogears.flash( _('A valid country and telephone number are' + ' required to complete the CLA. Please fill them ' + 'out below.')) cla = cla_done(person) person = person.filter_private() return dict(cla=cla, person=person, date=datetime.utcnow().ctime(), show=show) def _cla_dependent(self, group): ''' Check whether a group has the cla in its prerequisite chain. Arguments: :group: group to check Returns: True if the group requires the cla_group_name otherwise ''' if group.name in (self.CLAGROUPNAME, self.CLAMETAGROUPNAME): return True if group.prerequisite_id: return self._cla_dependent(group.prerequisite) return False def json_request(self): ''' Helps define if json is being used for this request :returns: 1 or 0 depending on if request is json or not ''' return 'tg_format' in cherrypy.request.params and \ cherrypy.request.params['tg_format'] == 'json' @expose(template="fas.templates.error") def error(self, tg_errors=None): '''Show a friendly error message''' if not tg_errors: turbogears.redirect('/') return dict(tg_errors=tg_errors) @identity.require(turbogears.identity.not_anonymous()) @expose(template="genshi-text:fas.templates.cla.cla", format="text", content_type='text/plain; charset=utf-8') def text(self): '''View CLA as text''' username = turbogears.identity.current.user_name person = People.by_username(username) person = person.filter_private() return dict(person=person, date=datetime.utcnow().ctime()) @identity.require(turbogears.identity.not_anonymous()) @expose(template="genshi-text:fas.templates.cla.cla", format="text", content_type='text/plain; charset=utf-8') def download(self): '''Download CLA''' username = turbogears.identity.current.user_name person = People.by_username(username) person = person.filter_private() return dict(person=person, date=datetime.utcnow().ctime()) @identity.require(turbogears.identity.not_anonymous()) @expose(template="fas.templates.user.view", allow_json=True) def reject(self, person_name): '''Reject a user's CLA. This method will remove a user from the CLA group and any other groups that they are in that require the CLA. It is used when a person has to fulfill some more legal requirements before having a valid CLA. Arguments :person_name: Name of the person to reject. ''' show = {} show['show_postal_address'] = config.get('show_postal_address') exc = None user = People.by_username(turbogears.identity.current.user_name) if not is_admin(user): # Only admins can use this turbogears.flash(_('You are not allowed to reject CLAs.')) exc = 'NotAuthorized' else: # Unapprove the cla and all dependent groups person = People.by_username(person_name) for role in person.roles: if self._cla_dependent(role.group): role.role_status = 'unapproved' try: session.flush() except SQLError, error: turbogears.flash(_('Error removing cla and dependent groups' \ ' for %(person)s\n Error was: %(error)s') % {'person': person_name, 'error': str(error)}) exc = 'sqlalchemy.SQLError' if not exc: # Send a message that the ICLA has been revoked date_time = datetime.utcnow() Log(author_id=user.id, description='Revoked %s CLA' % person.username, changetime=date_time) revoke_subject = _('Fedora ICLA Revoked') revoke_text = _(''' Hello %(human_name)s, We're sorry to bother you but we had to reject your CLA for now because information you provided has been deemed incorrect. The most common cause of this is people abbreviating their name like "B L Couper" instead of providing their actual full name "Bill Lay Couper". Other causes of this include are using a country, or phone number that isn't accurate [1]_. If you could edit your account [2]_ to fix any of these problems and resubmit the CLA we would appreciate it. .. [1]: Why does it matter that we have your real name and phone number? It's because the CLA is a legal document and should we ever need to contact you about one of your contributions (as an example, because someone contacts *us* claiming that it was really they who own the copyright to the contribution) we might need to contact you for more information about what's going on. .. [2]: Edit your account by logging in at this URL: %(editurl)s/accounts/user/edit/%(username)s If you have questions about what specifically might be the problem with your account, please contact us at [email protected]. Thanks! ''') % { 'username': person.username, 'human_name': person.human_name, 'editurl': config.get('base_url_filter.base_url').rstrip('/') } send_mail(person.email, revoke_subject, revoke_text) # Yay, sweet success! turbogears.flash(_('CLA Successfully Removed.')) # and now we're done if request_format() == 'json': return_val = {} if exc: return_val['exc'] = exc return return_val else: turbogears.redirect('/user/view/%s' % person_name)
except Exception, e: flash("Unable to connect to Koji") if request_format() == "json": return dict() raise redirect("/override/new") for build in iterate(builds): release = None n, v, r = get_nvr(build) # Make sure the build is tagged correctly try: tags = [tag["name"] for tag in koji.listTags(build)] except Exception, e: flash(str(e)) if request_format() == "json": return dict() raise redirect("/override/new") # Determine the release by the tag, and sanity check the builds for tag in tags: for rel in Release.select(): if tag in (rel.candidate_tag, rel.testing_tag): release = last_release = rel elif tag == rel.stable_tag: flash("Error: %s is already tagged with %s" % (build, tag)) if request_format() == "json": return dict() raise redirect("/override/new") if not release:
except Exception, e: flash('Unable to connect to Koji') if request_format() == 'json': return dict() raise redirect('/override/new') for build in iterate(builds): release = None n, v, r = get_nvr(build) # Make sure the build is tagged correctly try: tags = [tag['name'] for tag in koji.listTags(build)] except Exception, e: flash(str(e)) if request_format() == 'json': return dict() raise redirect('/override/new') # Determine the release by the tag, and sanity check the builds for tag in tags: for rel in Release.select(): if tag in (rel.candidate_tag, rel.testing_tag): release = last_release = rel elif tag == rel.stable_tag: flash('Error: %s is already tagged with %s' % ( build, tag)) if request_format() == 'json': return dict() raise redirect('/override/new') if not release: flash('Error: Could not determine release for %s with tags %s' %
except Exception, e: flash('Unable to connect to Koji') if request_format() == 'json': return dict() raise redirect('/override/new') for build in iterate(builds): release = None n, v, r = get_nvr(build) # Make sure the build is tagged correctly try: tags = [tag['name'] for tag in koji.listTags(build)] except Exception, e: flash(str(e)) if request_format() == 'json': return dict() raise redirect('/override/new') # Determine the release by the tag, and sanity check the builds for tag in tags: for rel in Release.select(): if tag in (rel.candidate_tag, rel.testing_tag): release = last_release = rel elif tag == rel.stable_tag: flash('Error: %s is already tagged with %s' % (build, tag)) if request_format() == 'json': return dict() raise redirect('/override/new') if not release: flash(
class BuildRootOverrideController(Controller): @identity.require(identity.not_anonymous()) @expose() def index(self): raise redirect('/override/list') @identity.require(identity.not_anonymous()) @expose(template="bodhi.templates.overrides", allow_json=True) @validate( validators={ 'build': validators.UnicodeString(), 'mine': validators.StringBool(), 'release': validators.UnicodeString(), 'show_expired': validators.StringBool() }) @paginate('overrides', default_order='-date_submitted', limit=20, max_limit=1000) def list(self, build=None, tg_errors=None, mine=False, release=None, show_expired=False, **kw): query = [] title = '%d Buildroot Overrides' if mine: query.append( BuildRootOverride.q.submitter == identity.current.user_name) title += ' submitted by %s' % identity.current.user_name if release: rel = Release.byName(release) query.append(BuildRootOverride.q.releaseID == rel.id) title += ' for %s' % rel.long_name if not show_expired: query.append(BuildRootOverride.q.date_expired == None) overrides = BuildRootOverride.select(AND(*query)) if request_format() == 'json': overrides = [o.__json__() for o in overrides] num_items = len(overrides) else: num_items = overrides.count() return dict(overrides=overrides, title=title % num_items, num_items=num_items, show_expired=show_expired, mine=mine) @identity.require(identity.not_anonymous()) @expose(template="bodhi.templates.form") def new(self, tg_errors=None, *args, **kw): if tg_errors: flash(str(tg_errors)) expiration = datetime.utcnow() + \ timedelta(days=config.get('buildroot_overrides.expire_after', 1)) return dict(form=override_form, values={'expiration': expiration}, action=url('/override/save'), title='Buildroot Overrides') @identity.require(identity.not_anonymous()) @expose(allow_json=True) def expire(self, build, *args, **kw): """ Expire a given override """ override = BuildRootOverride.byBuild(build) if override.date_expired: flash('Override %s already expired!' % build) if request_format() == 'json': return dict() raise redirect('/override') override.date_expired = datetime.utcnow() try: override.untag() except Exception, e: log.error(str(e)) flash(str(e)) raise redirect('/override') log.info('Buildroot override %s manually expired by %s' % (build, identity.current.user_name)) flash('Buildroot override for %s successful untagged' % build) if request_format() == 'json': return dict() raise redirect('/override')