def get_one(self, code): req = model.PasswordResetRequest.get(code) if req is None: redirect('/forgot/missing', internal=True) return dict(password_request=req)
def do_delete(self): source = request.context['recipe'] if source.author is None or source.author != request.context['user']: abort(401) source.delete() redirect("/")
def _post_login(self, *args, **kwargs): user = models.User.filter_by(username=kwargs['username']).first() if user: if user.validate_password(kwargs.get('password')): save_user_session(user) redirect('/') return dict(errors='wrong password or username', form_data=kwargs)
def decorate(self, *args, **kwargs): try: return func(self, *args, **kwargs) except exc.OAuthException as o_exc: # Extract the parameters error = o_exc.error error_description = o_exc.msg or _("No details available.") # If we have a redirect URL, build the error redirect. if o_exc.redirect_uri: # Split the redirect_url apart parts = urlparse(o_exc.redirect_uri) # Add the error and error_description if parts.query: params = urlparse.parse_qsl(parts.query) else: params = [] params.append(('error', error)) params.append(('error_description', error_description)) # Overwrite the old query params and reconstruct the URL parts_list = list(parts) parts_list[4] = urlencode(params) location = urlunparse(parts_list) redirect(location) else: error_body = { 'error': error, 'error_description': error_description } response.json = error_body abort(o_exc.code, error_description, json_body=error_body)
def _auth_failure(self, message): params = { 'message': message } url = parse.urljoin(CONF.ui_url, '/#/auth_failure?' + parse.urlencode(params)) pecan.redirect(url)
def get_all(self): # # If you're not logged in, and you already have a trial recipe, # redirect to *that* recipe so you can't create another one. # recipe = request.context['trial_recipe'] if request.context['user'] is None and recipe is not None: redirect(recipe.url(public=False)) form = request.pecan['form'] metric = request.context.get('metric') is True if request.context['user']: settings = request.context['user'].settings volume = settings['default_recipe_volume'] if metric: volume = round(to_metric(*(volume, 'GALLON'))[0], 3) form.process(**{ 'type': settings['default_recipe_type'], 'volume': format_volume(volume) }) else: form.process(**{ 'volume': 20 if metric else 5, 'unit': 'LITER' if metric else 'GALLON' }) return dict(form=form)
def callback(self, code=None, state=None): session = request.environ['beaker.session'] try: assert session['state'] == state except AssertionError: return 'Error: state mismatch' result = indieauth.request_token(session['me'], code) if not result: return 'Error: no token returned from token endpoint' target = 'https://www.indiepaper.io/indieauth.html?success=true' if session.get('app', False) == True: target += '&app=true' c = cookies.SimpleCookie() c['indiepaper-me'] = session['me'] c['indiepaper-me']['domain'] = '.indiepaper.io' c['indiepaper-me']['path'] = '/' c['indiepaper-token'] = result['token'] c['indiepaper-token']['domain'] = '.indiepaper.io' c['indiepaper-token']['path'] = '/' c['indiepaper-endpoint'] = result['micropub'] c['indiepaper-endpoint']['domain'] = '.indiepaper.io' c['indiepaper-endpoint']['path'] = '/' headers = [('Set-Cookie', morsel.OutputString()) for morsel in c.values()] redirect(target, headers=headers)
def jobs(self, machine_type=None, since_days=14): uri = '{base}/nodes/job_stats?since_days={days}'.format( base=base_url, days=since_days) if machine_type: uri += '&machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() statuses = ['pass', 'fail', 'dead', 'unknown', 'running'] for name in nodes.keys(): node = nodes[name] total = sum(node.values()) node['total'] = total for status in statuses: if node.get(status) is None: node[status] = 0 nodes = OrderedDict( sorted(nodes.items(), key=lambda t: t[1]['total'], reverse=True)) title_templ = "{days}-day stats for {mtype} nodes" title = title_templ.format(days=since_days, mtype=(machine_type or 'all')) return dict( title=title, nodes=nodes, count=len(nodes), )
def locks(self, machine_type=None): uri = '{base}/nodes/?up=True'.format( base=base_url, ) if machine_type: uri += '&machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() users = dict() print nodes for node in nodes: if node.get('locked', False): owner = node.get('locked_by') else: owner = '(free)' mtype = node.get('machine_type') type_dict = users.get(owner, dict()) type_dict[mtype] = type_dict.get(mtype, 0) + 1 users[owner] = type_dict title = "Machine usage for up {mtype}nodes".format( mtype=machine_type + ' ' if machine_type else '', ) return dict( title=title, users=users, )
def index_post(self): jsboard = loads(request.body) board = ShiftyBoard.query.get(name=jsboard['name']) if board: abort(409, detail='Name already in use: %s' % board.name) board = ShiftyBoard() try: board.name = jsboard['name'] board.dimensions = (jsboard['dimensions']['cols'], jsboard['dimensions']['rows']) board.start = (jsboard['start'][0], jsboard['start'][1]) for tile, col, row in jsboard['goals']: board.add_goal(tile, col=col, row=row) for col in range(0, board.dimensions[0]): for row in range(0, board.dimensions[1]): board[col][row] = jsboard['tiles'][col][row] except Exception as e: abort(406, 'Configuration error for board: %s' % e) model.commit() redirect('/boards/%s/' % board.name, code=303)
def aodh_redirect(url): # NOTE(sileht): we use 307 and not 301 or 302 to allow # client to redirect POST/PUT/DELETE/... # FIXME(sileht): it would be better to use 308, but webob # doesn't handle it :( # https://github.com/Pylons/webob/pull/207 pecan.redirect(location=url + pecan.request.path_qs, code=307)
def signin(self): """Handle signin request.""" session = api_utils.get_user_session() if api_utils.is_authenticated(): pecan.redirect(CONF.ui_url) else: api_utils.delete_params_from_user_session([const.USER_OPENID]) csrf_token = api_utils.get_token() session[const.CSRF_TOKEN] = csrf_token session.save() return_endpoint = parse.urljoin(CONF.api.api_url, CONF.osid.openid_return_to) return_to = api_utils.set_query_params(return_endpoint, {const.CSRF_TOKEN: csrf_token}) params = { const.OPENID_MODE: CONF.osid.openid_mode, const.OPENID_NS: CONF.osid.openid_ns, const.OPENID_RETURN_TO: return_to, const.OPENID_CLAIMED_ID: CONF.osid.openid_claimed_id, const.OPENID_IDENTITY: CONF.osid.openid_identity, const.OPENID_REALM: CONF.api.api_url, const.OPENID_NS_SREG: CONF.osid.openid_ns_sreg, const.OPENID_NS_SREG_REQUIRED: CONF.osid.openid_sreg_required, } url = CONF.osid.openstack_openid_endpoint url = api_utils.set_query_params(url, params) pecan.redirect(location=url)
def index(self, machine_type=None): uri = urljoin(base_url, '/nodes/') if machine_type: uri += '?machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() for node in nodes: set_node_status_class(node) # keep only the node name, not the fqdn node['fqdn'] = node['name'] node['name'] = node['fqdn'].split(".")[0] desc = node['description'] if not desc or desc.lower() == "none": node['description'] = "" elif 'teuthworker' in desc: # strip out the path part of the description and # leave it with the run_name/job_id node['description'] = "/".join(desc.split("/")[-2:]) nodes.sort(key=lambda n: n['name']) title = "{mtype} nodes".format( mtype=machine_type if machine_type else 'All', ) return dict( title=title, nodes=nodes, )
def index(self): if not self.exists(): redirect('/errors/notfound') return { 'name': self.name, 'graphite_url': conf.graphite_url }
def signin_return(self): """Handle returned request from OpenID 2.0 IdP.""" session = api_utils.get_user_session() if pecan.request.GET.get(const.OPENID_ERROR): api_utils.delete_params_from_user_session([const.CSRF_TOKEN]) self._auth_failure(pecan.request.GET.get(const.OPENID_ERROR)) if pecan.request.GET.get(const.OPENID_MODE) == 'cancel': api_utils.delete_params_from_user_session([const.CSRF_TOKEN]) self._auth_failure('Authentication canceled.') session_token = session.get(const.CSRF_TOKEN) request_token = pecan.request.GET.get(const.CSRF_TOKEN) if request_token != session_token: api_utils.delete_params_from_user_session([const.CSRF_TOKEN]) self._auth_failure('Authentication failed. Please try again.') api_utils.verify_openid_request(pecan.request) user_info = { 'openid': pecan.request.GET.get(const.OPENID_CLAIMED_ID), 'email': pecan.request.GET.get(const.OPENID_NS_SREG_EMAIL), 'fullname': pecan.request.GET.get(const.OPENID_NS_SREG_FULLNAME) } user = db.user_save(user_info) api_utils.delete_params_from_user_session([const.CSRF_TOKEN]) session[const.USER_OPENID] = user.openid session.save() pecan.redirect(CONF.ui_url)
def error(url, msg=None): """ Helper for controller methods to do an internal redirect with either a url part like:: error("/errors/not_allowed/") Or an http code:: error(404) The ``msg`` argument is optional and would override the default error message for each error condition as defined in the ``ErrorController`` methods. """ code_to_url = { 400: '/errors/invalid/', 403: '/errors/forbidden/', 404: '/errors/not_found/', 405: '/errors/not_allowed/', 500: '/errors/error/', 503: '/errors/unavailable/', } if isinstance(url, int): url = code_to_url.get(url, 500) if msg: request.context['message'] = msg url = path.join(url, '?message=%s' % msg) redirect(url, internal=True)
def locks(self, machine_type=None): uri = urljoin(base_url, '/nodes/?up=True') if machine_type: uri += '&machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() users = dict() for node in nodes: if node.get('locked', False): owner = node.get('locked_by') else: owner = '(free)' mtype = node.get('machine_type') type_dict = users.get(owner, dict()) type_dict[mtype] = type_dict.get(mtype, 0) + 1 users[owner] = type_dict title = "Machine usage for up {mtype}nodes".format( mtype=machine_type + ' ' if machine_type else '', ) return dict( title=title, users=users, )
def redirect_to_handler(form, location): """ Cause a form with error to internally redirect to a URI path. This is generally for internal use, but can be called from within a Pecan controller to trigger a validation failure from *within* the controller itself, e.g.:: @expose() @with_form(SomeForm, error_cfg={ 'auto_insert_errors': True, 'handler': '/some/handler' }) def some_controller(self, **kw): if some_bad_condition(): form = pecan.request.pecan['form'] form.some_field.errors.append('Validation failure!') redirect_to_handler(form, '/some/handler') """ setattr(form, '_validation_original_data', request.params) if callable(location): location = location() request.environ['REQUEST_METHOD'] = 'GET' request.environ['pecan.validation_redirected'] = True request.environ['pecan.validation_form'] = form redirect(location, internal=True)
def index(self, machine_type=None): uri = '{base}/nodes/'.format( base=base_url, ) if machine_type: uri += '?machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() for node in nodes: set_node_status_class(node) nodes.sort(key=lambda n: n['name']) title = "{mtype} nodes".format( mtype=machine_type if machine_type else 'All', ) return dict( title=title, nodes=nodes, )
def index(self, machine_type=None): uri = urlparse.urljoin(base_url, '/nodes/') if machine_type: uri += '?machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() for node in nodes: set_node_status_class(node) # keep only the node name, not the fqdn node['fqdn'] = node['name'] node['name'] = node['fqdn'].split(".")[0] desc = node['description'] if not desc or desc.lower() == "none": node['description'] = "" elif 'teuthworker' in desc: # strip out the path part of the description and # leave it with the run_name/job_id node['description'] = "/".join(desc.split("/")[-2:]) nodes.sort(key=lambda n: n['name']) title = "{mtype} nodes".format( mtype=machine_type if machine_type else 'All', ) return dict( title=title, nodes=nodes, )
def jobs(self, machine_type=None, since_days=14): uri = urljoin(base_url, '/nodes/job_stats?since_days={0}'.format(since_days)) if machine_type: uri += '&machine_type=%s' % machine_type resp = requests.get(uri, timeout=60) if resp.status_code == 502: redirect('/errors?status_code={status}&message={msg}'.format( status=200, msg='502 gateway error :('), internal=True) elif resp.status_code == 400: error('/errors/invalid/', msg=resp.text) nodes = resp.json() statuses = ['pass', 'fail', 'dead', 'unknown', 'running'] for name in nodes.keys(): node = nodes[name] total = sum(node.values()) node['total'] = total for status in statuses: if node.get(status) is None: node[status] = 0 nodes = OrderedDict( sorted(nodes.items(), key=lambda t: t[1]['total'], reverse=True)) title_templ = "{days}-day stats for {mtype} nodes" title = title_templ.format(days=since_days, mtype=(machine_type or 'all')) return dict( title=title, nodes=nodes, count=len(nodes), )
def check_permissions(cls): if request.context['user'] is None: notify( 'Sign up for a (free) account to take advantage of this ' 'feature.' ) redirect('/signup', headers=response.headers) return True
def index_post(self, **kw): user = request.context['user'] for k,v in kw.items(): setattr(user, k, v) notify('Your settings have been saved.') redirect('/settings/profile', headers=response.headers)
def repo(self, **kw): repo_url = get_repo_url( self.repo_query, kw.get('arch'), ) if not repo_url: abort(504, "no repository is ready for: %s/%s" % (self.project.name, self.ref_name)) redirect(repo_url)
def error(url, msg=None, **kwargs): """Error handler""" if msg: pecan.request.context['error_message'] = msg if kwargs: pecan.request.context['kwargs'] = kwargs url = path.join(url, '?error_message=%s' % msg) pecan.redirect(url, internal=True)
def signout(self): """Handle signout request.""" if api_utils.is_authenticated(): api_utils.delete_params_from_user_session([const.USER_OPENID]) params = {'openid_logout': CONF.osid.openid_logout_endpoint} url = parse.urljoin(CONF.ui_url, '/#/logout?' + parse.urlencode(params)) pecan.redirect(url)
def __init__(self, slug): self.slug = slug # Make sure the provided slug is valid if not slug: redirect(request.context['recipe'].slugs[0].slug) if slug not in [slug.slug for slug in request.context['recipe'].slugs]: abort(404)
def repo(self, **kw): arch = kw.get('arch', 'x86_64') # requires the repository to be fully available on a remote chacra # instance for a proper redirect. Otherwise it will fail explicitly repo = self.repo_query.filter_by(status='ready').join(Arch).filter( Arch.name == arch).first() if not repo: abort(504, detail="no repository is available yet") redirect(os.path.join(repo.chacra_url, 'repo'))
def do_draft(self): source = request.context['recipe'] if source.author is None or source.author != request.context['user']: abort(401) if source.state != "PUBLISHED": abort(401) draft = source.draft() draft.flush() redirect("%sbuilder" % draft.url())
def _default(self, arch, *args): repo_url = get_repo_url( self.repo_query, arch, path=args, repo_file=False, ) if not repo_url: abort(504, "no repository is ready for: %s/%s" % (self.project.name, self.ref_name)) redirect(repo_url)
def repo(self, **kw): repo_url = get_repo_url( self.repo_query, kw.get('arch'), ) if not repo_url: abort( 504, "no repository is ready for: %s/%s" % (self.project.name, self.ref_name)) redirect(repo_url)
def repo(self, **kw): arch = kw.get('arch', 'x86_64') # requires the repository to be fully available on a remote chacra # instance for a proper redirect. Otherwise it will fail explicitly repo = self.repo_query.filter_by(status='ready').join(Arch).filter(Arch.name == arch).first() if not repo: abort(504, detail="no repository is available yet") redirect( os.path.join(repo.chacra_url, 'repo') )
def get_all(self): # # If you're not logged in, and you already have a trial recipe, # redirect to *that* recipe so you can't create another one. # recipe = request.context['trial_recipe'] if request.context['user'] is None and recipe is not None: redirect(recipe.url(public=False)) return dict()
def _redirect_to_default_json_home_if_needed(self, request): if self._mime_best_match(request.accept) == MIME_TYPE_JSON_HOME: url = _get_versioned_url(DEFAULT_VERSION) LOG.debug("Redirecting Request to " + url) # NOTE(jaosorior): This issues an "external" redirect because of # two reasons: # * This module doesn't require authorization, and accessing # specific version info needs that. # * The resource is a separate app_factory and won't be found # internally pecan.redirect(url, request=request)
def index(self): if request.method == 'POST': upload = request.POST.get('upload') filename = upload.filename file_obj = upload.file if not filename.endswith('tar.gz'): redirect('/errors/unable', internal=True) self.save_file(filename, file_obj) return dict() else: return "You probably want to POST a file right?"
def index_post(self, **kw): user = request.context['user'] form = request.pecan['form'] if form.errors: return dict(user=user, form=form) for k, v in kw.items(): setattr(user, k, v) notify('Your settings have been saved.') redirect('/settings/profile', headers=response.headers)
def signout(self): """Handle signout request.""" if api_utils.is_authenticated(): api_utils.delete_params_from_user_session([const.USER_OPENID]) params = { 'openid_logout': CONF.osid.openid_logout_endpoint } url = parse.urljoin(CONF.ui_url, '/#/logout?' + parse.urlencode(params)) pecan.redirect(url)
def _post_login(self, **kw): username = kw.get('username') password = kw.get('password') user = model.User.get_by(username=username) save_user_session(user) if request.context['trial_recipe']: request.context['trial_recipe'].author = user remove_trial_recipe() redirect('/')
def _default(self, arch, *args): repo_url = get_repo_url( self.repo_query, arch, path=args, repo_file=False, ) if not repo_url: abort( 504, "no repository is ready for: %s/%s" % (self.project.name, self.ref_name)) redirect(repo_url)
def wget_package(self): try: browse = BrowsePyPi(self.name, self.dir) browse.grab_package() except: for mirror in pecan.conf.pypi_urls: try: address = "%s%s" % (mirror, self.name) logger.debug('redirecting to PyPi mirror [%s] since caral does not have package %s' % (mirror, self.name)) redirect(address) except: continue
def index_post(self, **kw): user = request.context['user'] for k, v in kw.items(): user.settings[k] = v if request.context['metric'] is True: user.settings['default_recipe_volume'] = to_us( *(user.settings['default_recipe_volume'], 'LITER'))[0] user.settings['brewhouse_efficiency'] /= 100.00 notify('Your settings have been saved.') redirect('/settings/recipe', headers=response.headers)
def _post(self, **kw): username = kw['username'] password = kw['password'] email = kw['email'].replace(' ', '') user = model.User(username=username, password=password, email=email) if request.context['trial_recipe']: request.context['trial_recipe'].author = user remove_trial_recipe() request.context['__signup_email__'] = email request.context['__signup_username__'] = username pecan.redirect('/login?welcome')
def do_post(self, email): # Generate a random hash code = sha256(str(uuid1())).hexdigest() u = model.User.get_by(email=email) assert u is not None # Store a password request for this user model.PasswordResetRequest( code=code, user=u ) # Generate the email emaillib.send( u.email, 'forgot', 'Reset Your Draughtcraft Password', { 'name': u.printed_name, 'code': code } ) notify(("We've received your reset request. You should receive an " "email with instructions shortly.")) return redirect('/login', headers=response.headers)
def request_authorization(me, state): endpoints = discover_endpoints(me) if len(endpoints.get('authorization_endpoint', [])) == 0: raise Exception('No authorization endpoint discovered.') auth_endpoint = endpoints['authorization_endpoint'].pop().geturl() ns = { 'me': me, 'redirect_uri': 'https://indiepaper.io/indieauth/callback', 'client_id': 'https://indiepaper.io', 'state': state, 'scope': 'save create update', 'response_type': 'code' } auth_target = auth_endpoint + '?' + urlencode(ns) redirect(auth_target)
def post(self, code, **kw): req = model.PasswordResetRequest.get(code) if req is None: redirect('/forgot/missing', internal=True) u = req.user if u.email != kw.get('email').strip(): form = request.pecan['form'] form.email.errors.append( "Sorry, that email address is not valid." ) redirect_to_handler(form, request.path) # Delete the password request and change their password. req.delete() u.password = kw.get('password') notify("Your password has been reset. Go ahead and log in.") return redirect('/login', headers=response.headers)
def redirect_to_handler(error, location): """ Cause a requset with an error to internally redirect to a URI path. This is generally for internal use, but can be called from within a Pecan controller to trigger a validation failure from *within* the controller itself, e.g.:: @expose() @validate(some_schema, '/some/handler') def some_controller(self, **kw): if some_bad_condition(): error_exception = ... redirect_to_handler(error_exception, '/some/handler') """ if callable(location): location = location() request.environ['REQUEST_METHOD'] = 'GET' redirect(location, internal=True)
def do_copy(self): source = request.context['recipe'] if request.context['user'] is None: redirect("/signup") if source.author is None: abort(401) diff_user = source.author != request.context['user'] name = source.name if diff_user else "%s (Duplicate)" % source.name copy = source.duplicate({ 'name': name, 'author': request.context['user'] }) if diff_user: copy.copied_from = source redirect("/")