def handle_redirect_on_success(request, backurl=None): """Will return a redirect. If there has been a saved "backurl" the redirect will on on this url. In all other cases the function will try to determine if the item in the request can be opened in edit mode or not. If the current user is allowed to open the item in edit mode then the update view is called. Else the read view is called. :request: Current request :backurl: Optional. Set backurl manually. This will overwrite backurls saved in the session. :returns: Redirect """ item = get_item_from_request(request) clazz = request.context.__model__ backurl = backurl or request.session.get("%s.backurl" % clazz) if backurl: # Redirect to the configured backurl. if request.session.get("%s.backurl" % clazz): del request.session["%s.backurl" % clazz] request.session.save() return HTTPFound(location=backurl) else: # Handle redirect after success. # Check if the user is allowed to call the url after saving if has_permission("update", item, request): route_name = get_action_routename(item, "update") url = request.route_path(route_name, id=item.id) else: route_name = get_action_routename(item, "read") url = request.route_path(route_name, id=item.id) return HTTPFound(location=url)
def render_file_preview(request, item, column, tableconfig): """Returns HTML code to embed a small preview of the file in the overview""" if isinstance(item, tuple): item = item[0] url = request.route_path(get_action_routename(item, "download"), id=item.id) return literal('<embed src="{}" height="25" type="{}">'.format(url, item.mime))
def _get_template_values(self): values = FieldRenderer._get_template_values(self) request = self._field._form._request item = self._field._form._item values["url"] = request.route_path(get_action_routename(item, "download"), id=item.id) values["mime"] = item.mime return values
def handle_redirect_on_success(request, backurl=None): """Will return a redirect. If there has been a saved "backurl" the redirect will on on this URL. In all other cases the function will try to determine if the item in the request can be opened in edit mode or not. If the current user is allowed to open the item in edit mode then the update view is called. Else the read view is called. :request: Current request :backurl: Optional. Set backurl manually. This will overwrite backurl saved in the session. :returns: Redirect """ item = get_item_from_request(request) clazz = request.context.__model__ backurl = backurl or request.session.get('%s.backurl' % clazz) if request.session.get('%s.backurl' % clazz): del request.session['%s.backurl' % clazz] request.session.save() if backurl and (request.params.get("_submit") not in ["stay", "nextpage"]): # Ignore the redirect to the backurl if the user clicks on # "Save" and "Save and proceed" Buttons. In this case a special # value is part of the form. In case of "Save and return" or # the default submittbuttons with no special value we keep the # old behavior. return HTTPFound(location=backurl) elif request.path.find("/create") > -1 or request.path.find( "/update") > -1: # Handle redirect after success.in case of a create. # Check if the user is allowed to call the url after saving if has_permission("update", item, request): route_name = get_action_routename(item, 'update') url = request.route_path(route_name, id=item.id) else: route_name = get_action_routename(item, 'read') url = request.route_path(route_name, id=item.id) return HTTPFound(location=url) else: # Handle all other variants of the redirect and stay on the # current url. return HTTPFound(location=request.url)
def _get_template_values(self): values = FieldRenderer._get_template_values(self) request = self._field._form._request item = self._field._form._item values["url"] = request.route_path(get_action_routename( item, "download"), id=item.id) values["mime"] = item.mime values["item"] = item return values
def get_link_url(item, request, actionname=None, backurl=False): """Return a url to the given item. On default the link will be a link to the update or read view of the item depending on the permission. If the application is configured to open items in read mode on default the update action will not be checked. If the user does not have enough permissions than None is returned. Optionally you can provide the name of a action. In this case the url will be build for the given actionname if the user has enough permissions.""" readmode = request.registry.settings.get("app.readmode") in [ "True", "true" ] if isinstance(item, BaseItem): if actionname: from ringo.views.helpers import get_item_modul modul = get_item_modul(request, item) action = modul.get_action(actionname) if action is None: # This can happen if the action is not part of the modul # but a custum userdefined view. No permission checks # are done here yet. route_name = get_action_routename(item, actionname) else: permission = action.permission or action.name.lower() if security.has_permission(permission, item, request): route_name = get_action_routename(item, action.name.lower()) else: return None elif not readmode and security.has_permission("update", item, request): route_name = get_action_routename(item, 'update') elif security.has_permission("read", item, request): route_name = get_action_routename(item, 'read') else: return None query = {} if backurl: clazz = request.context.__model__ query['backurl'] = request.session.get( '%s.backurl' % clazz) or request.current_route_path() return request.route_path(route_name, id=item.id, _query=query) return None
def _setup_rest_action(config, action, clazz, view_mapping): """Setup a route and a view for given action and clazz. The routes will have the follwoing following name and url: * Name: $modulname-$actionname * Url: $modulname/$actionurl Note, that the actionname can be configured only as admin. Further a clazz specific factory will be added to the route which is later used to setup the ACL of items of the modul. :config: Configuration :action: Action item :clazz: clazz item :view_mapping: Dictionary with action items :returns: @todo """ action_method_mapping = { "list": "GET", "create": "POST", "read": "GET", "update": "PUT", "delete": "DELETE" } name = clazz.__tablename__ action_name = action.name.lower() view_func = get_action_view(view_mapping, action_name, name) if not view_func: return route_name = get_action_routename(clazz, action_name, prefix="rest") tmpurl = action.url.split("/") if len(tmpurl) > 1: route_url = "rest/%s/%s" % (name, tmpurl[1]) else: route_url = "rest/%s" % (name) log.debug("Adding REST route: %s, %s" % (route_name, route_url)) method = action_method_mapping[action_name] config.add_route(route_name, route_url, request_method=method, factory=get_resource_factory(clazz)) log.debug("Adding REST view: %s, %s, %s" % (view_func, route_name, method)) settings = config.registry.settings http_cache = settings.get('security.page_http_cache', '0') config.add_view(view_func, route_name=route_name, request_method=method, renderer='json', permission=action.permission or action_name, http_cache=int(http_cache))
def includeme(config): # Now configure the application and optionally overwrite previously translators.append(TranslationStringFactory('plorma')) config.add_translation_dirs('plorma:locale/') config.add_static_view('plorma-static', path='plorma:static', cache_max_age=3600) config.add_route('renderburndown', 'sprints/burndown/{id}', factory=get_resource_factory(Sprint)) config.add_route(get_action_routename(Sprint, 'board'), 'sprintboard/{id}', factory=get_resource_factory(Sprint))
def render(self, items): values = {} values['request'] = self._request values['body'] = self._render_body() values['modul'] = get_item_modul(self._request, self._item).get_label(plural=True) values['action'] = self._action.capitalize() values['ok_url'] = self._request.current_route_path() values['_'] = self._request.translate values['cancel_url'] = self._request.referrer values['overview_url'] = self._request.route_path(get_action_routename(self._item, 'list')) values['eval_url'] = self._request.application_url+get_eval_url() values['items'] = items values['h'] = ringo.lib.helpers return literal(self.template.render(**values))
def get_link_url(item, request, actionname=None, backurl=False): """Return a url to the given item. On default the link will be a link to the update or read view of the item depending on the permission. If the user does not have enough permissions than None is returned. Optionally you can provide the name of a action. In this case the url will be build for the given actionname if the user has enough permissions.""" if isinstance(item, BaseItem): if actionname: from ringo.views.helpers import get_item_modul modul = get_item_modul(request, item) action = modul.get_action(actionname) if action is None: # This can happen if the action is not part of the modul # but a custum userdefined view. No permission checks # are done here yet. route_name = get_action_routename(item, actionname) else: permission = action.permission or action.name.lower() if security.has_permission(permission, item, request): route_name = get_action_routename(item, action.name.lower()) else: return None elif security.has_permission("update", item, request): route_name = get_action_routename(item, 'update') elif security.has_permission("read", item, request): route_name = get_action_routename(item, 'read') else: return None query = {} if backurl: query['backurl'] = request.current_route_path() return request.route_path(route_name, id=item.id, _query=query) return None
def includeme(config): """Registers a new modul for ringo. :config: Dictionary with configuration of the new modul """ modul = register_modul(config, modul_config) News._modul_id = modul.get_value("id") translators.append(TranslationStringFactory('ringo_news')) config.add_translation_dirs('ringo_news:locale/') config.add_route(get_action_routename(News, 'markasread', prefix="rest"), 'rest/news/{id}/markasread', factory=get_resource_factory(News)) config.scan()
def _handle_redirect(request): """Will return a redirect. :request: Current request :returns: Redirect """ clazz = request.context.__model__ backurl = request.session.get('%s.backurl' % clazz) if backurl: # Redirect to the configured backurl. del request.session['%s.backurl' % clazz] request.session.save() return HTTPFound(location=backurl) else: # Redirect to the list view. route_name = get_action_routename(clazz, 'list') url = request.route_path(route_name) return HTTPFound(location=url)
def restore(request): clazz = request.context.__model__ _ = request.translate handle_params(request) handle_history(request) item = get_item_from_request(request) item_label = get_item_modul(request, clazz).get_label(plural=True) mapping = {'item_type': item_label, 'item': item} item.trash_state_id = 1 route_name = get_action_routename(item, 'update') url = request.route_path(route_name, id=item.id) msg = _('Restored ${item} from trash successfully.', mapping=mapping) log_msg = u'User {user.login} restored {item_label} {item.id}'.format( item_label=item_label, item=item, user=request.user) log.info(log_msg) request.session.flash(msg, 'success') transaction.commit() return HTTPFound(location=url)
def get_read_update_url(request, item, clazz, prefilterd=False): """Helper method to get the URL to read or update in item in various overviews. If the user of this request is not allowed to see the item at all, None will be returned as the url.""" permissions = ['read'] # If the application is configured to open items in readmode on # default then we will not add the update action to the actions to # check. if not request.registry.settings.get("app.readmode") in ["True", "true"]: permissions.append('update') is_admin = request.user.has_role("admin") url = None for permission in permissions: if (permission == 'read' and prefilterd) \ or is_admin \ or security.has_permission(permission, item, request): url = request.route_path(get_action_routename(clazz, permission), id=item.id) else: break return url
def test_get_action_routename_prefixed(self): from ringo.model.modul import ModulItem from ringo.lib.helpers import get_action_routename result = get_action_routename(ModulItem, 'create', 'rest') self.assertEqual(result, 'rest-modules-create')
def changepassword(request): """Method to change the users password by the user. The user user musst provide his old and the new pasword. Users are only allowed to change their own password.""" # Check authentification # As this view has now security configured it is # generally callable by all users. For this reason we first check if # the user is authenticated. If the user is not authenticated the # raise an 401 (unauthorized) exception. if not request.user: raise HTTPUnauthorized clazz = User _ = request.translate rvalue = {} # Load the item return 400 if the item can not be found. id = request.matchdict.get('id') factory = clazz.get_item_factory() try: item = factory.load(id, request.db) # Check authorisation # User are only allowed to set their own password. if item.id != request.user.id: raise HTTPForbidden() except sa.orm.exc.NoResultFound: raise HTTPBadRequest() form = Form(get_form_config(item, 'changepassword'), item, request.db, translate=_, renderers={}, change_page_callback={'url': 'set_current_form_page', 'item': clazz.__tablename__, 'itemid': id}, request=request, csrf_token=request.session.get_csrf_token()) if request.POST: mapping = {'item': item} # Do extra validation which is not handled by formbar. # Is the provided old password correct? validator = Validator('oldpassword', _('The given password is not correct'), check_password) pw_len_validator = Validator('password', _('Password must be at least 12 ' 'characters long.'), password_minlength_validator) pw_nonchar_validator = Validator('password', _('Password must contain at least 2 ' 'non-letters.'), password_nonletter_validator) form.add_validator(validator) form.add_validator(pw_len_validator) form.add_validator(pw_nonchar_validator) if form.validate(request.params): form.save() # Actually save the password. This is not done in the form # as the password needs to be encrypted. encrypt_password_callback(request, item) msg = _('Changed password for "${item}" successfull.', mapping=mapping) log.info(msg) request.session.flash(msg, 'success') route_name = get_action_routename(item, 'changepassword') url = request.route_path(route_name, id=item.id) # Invalidate cache invalidate_cache() return HTTPFound(location=url) else: msg = _('Error on changing the password for ' '"${item}".', mapping=mapping) log.info(msg) request.session.flash(msg, 'error') rvalue['clazz'] = clazz rvalue['item'] = item rvalue['form'] = form.render(page=get_current_form_page(clazz, request)) return rvalue
# Only consider names for the other users return db.query(User).filter(User.login == data[field], ~(User.id == params['pk'])).count() == 0 def password_nonletter_validator(field, data): """Validator to ensure that passwords contain two non-letters""" return len(re.findall('[^a-zA-ZäöüÄÖÜß]', data[field])) >= 2 def password_minlength_validator(field, data): """Validator to ensure that passwords are at least 12 characters long.""" return len(data[field]) >= 12 @view_config(route_name=get_action_routename(User, 'create'), renderer='/default/create.mako', permission='create') def create_(request, callback=None): """View to create new users. This view also take a optional callback parameter which can be used to inject additional callbacks in case this view is owerwritten in another application. :request: Current request :callback: Optional paramter for callback(s) """ callbacks = [] callbacks.append(user_create_callback) if callback: if isinstance(callback, list):
import logging from pyramid.view import view_config from ringo.lib.helpers import get_action_routename from ringo.lib.form import get_path_to_form_config from ringo.views.base import create from ringo.model.form import Form log = logging.getLogger(__name__) def load_config(path): data = "" with open(path) as f: data = f.read() return data @view_config(route_name=get_action_routename(Form, 'create'), renderer='/default/create.mako', permission='create') def create_(request): clazz = request.context.__model__ factory = clazz.get_item_factory() form = factory.create(request.user, values={}) definition = load_config(get_path_to_form_config("blobform_template.xml", "ringo")) form.definition = definition request.context.item = form return create(request)
chart.add(_('Ideal'), ideal) response = Response(chart.render(), content_type="image/svg+xml") return response def create_callback(request, sprint): return update_callback(request, sprint) def update_callback(request, sprint): for log in sprint.estimatelog: if log.date == datetime.date.today(): log.estimate = sprint.estimate return sprint nlog = Estimatelog() nlog.estimate = sprint.estimate nlog.date = datetime.date.today() sprint.estimatelog.append(nlog) @view_config(route_name=get_action_routename(Sprint, 'create'), renderer='/default/create.mako', permission='create') def create_(request): return create(request, create_callback) @view_config(route_name=get_action_routename(Sprint, 'update'), renderer='/default/update.mako', permission='update') def update_(request): return update(request, update_callback)
def _setup_web_action(config, action, clazz, view_mapping): """Setup a route and a view for given action and clazz. The routes will have the follwoing following name and url: * Name: $modulname-$actionname * Url: $modulname/$actionurl Note, that the actionname can be configured only as admin. Further a clazz specific factory will be added to the route which is later used to setup the ACL of items of the modul. :config: Configuration :action: Action item :clazz: clazz item :view_mapping: Dictionary with action items :returns: @todo """ name = clazz.__tablename__ action_name = action.name.lower() route_name = get_action_routename(clazz, action_name) route_url = "%s/%s" % (name, action.url) log.debug("Adding WEB route: %s, %s" % (route_name, route_url)) config.add_route(route_name, route_url, factory=get_resource_factory(clazz)) settings = config.registry.settings http_cache = settings.get('security.page_http_cache', '0') view_func = get_action_view(view_mapping, action_name, name) if view_func: if action_name == "delete": template = "confirm" renderer = '/default/%s.mako' % template elif action_name == "download": renderer = None else: template = action_name renderer = '/default/%s.mako' % template config.add_view(view_func, route_name=route_name, renderer=renderer, permission=action.permission or action_name, http_cache=int(http_cache)) ## Add bundle action. if action_name == "list": action_name = "bundle" route_name = "%s-%s" % (name, action_name) route_url = "%s/%s" % (name, action_name) view_func = get_action_view(view_mapping, action_name, name) log.debug("Adding route: %s, %s" % (route_name, route_url)) config.add_route(route_name, route_url, factory=get_resource_factory(clazz)) config.add_view(view_func, route_name=route_name, renderer='/default/bundle.mako', permission='list') ## Add permission action. if action_name == "read": action_name = "ownership" route_name = "%s-%s" % (name, action_name) route_url = "%s/%s/{id}" % (name, action_name) view_func = get_action_view(view_mapping, action_name, name) log.debug("Adding route: %s, %s" % (route_name, route_url)) config.add_route(route_name, route_url, factory=get_resource_factory(clazz)) config.add_view(view_func, route_name=route_name, renderer='/default/update.mako', permission='read')
def changepassword(request): """Method to change the users password by the user. The user user musst provide his old and the new pasword. Users are only allowed to change their own password.""" # Check authentification # As this view has now security configured it is # generally callable by all users. For this reason we first check if # the user is authenticated. If the user is not authenticated the # raise an 401 (unauthorized) exception. if not request.user: raise HTTPUnauthorized clazz = User handle_history(request) handle_params(request) _ = request.translate rvalue = {} # Load the item return 400 if the item can not be found. id = request.matchdict.get('id') factory = clazz.get_item_factory() try: item = factory.load(id, request.db) # Check authorisation # User are only allowed to set their own password. if item.id != request.user.id: raise HTTPForbidden() except sa.orm.exc.NoResultFound: raise HTTPBadRequest() form = Form(get_form_config(item, 'changepassword'), item, request.db, translate=_, renderers={}, change_page_callback={'url': 'set_current_form_page', 'item': clazz.__tablename__, 'itemid': id}, request=request, csrf_token=request.session.get_csrf_token()) if request.POST: mapping = {'item': item} # Do extra validation which is not handled by formbar. # Is the provided old password correct? validator = Validator('oldpassword', _('The given password is not correct'), check_password) pw_len_validator = Validator('password', _('Password must be at least 12 ' 'characters long.'), password_minlength_validator) pw_nonchar_validator = Validator('password', _('Password must contain at least 2 ' 'non-letters.'), password_nonletter_validator) form.add_validator(validator) form.add_validator(pw_len_validator) form.add_validator(pw_nonchar_validator) if form.validate(request.params): form.save() # Actually save the password. This is not done in the form # as the password needs to be encrypted. encrypt_password_callback(request, item) msg = _('Changed password for "${item}" successfull.', mapping=mapping) log.info(msg) request.session.flash(msg, 'success') route_name = get_action_routename(item, 'changepassword') url = request.route_path(route_name, id=item.id) # Invalidate cache invalidate_cache() return HTTPFound(location=url) else: msg = _('Error on changing the password for ' '"${item}".', mapping=mapping) log.info(msg) request.session.flash(msg, 'error') rvalue['clazz'] = clazz rvalue['item'] = item rvalue['form'] = form.render(page=get_current_form_page(clazz, request)) return rvalue
#!/usr/bin/env python # -*- coding: utf-8 -*- from pyramid.view import view_config from ringo.lib.helpers import get_action_routename from ringo.views.base import update, read from ringo.views.request import get_item_from_request from ringo.views.response import JSONResponse from trainable.model.activity import Activity from trainable.views.strava import sync_activity @view_config(route_name=get_action_routename(Activity, "sync"), renderer="/default/update.mako", permission="update") def syncwithstrava(request): """Will update the activity with strava in with all details.""" request.item = sync_activity(request) _ = request.translate msg = _('The activity was successfully synchronized with Strava') request.session.flash(msg, "success") return update(request) @view_config(route_name=get_action_routename(Activity, "update"), renderer="/default/update.mako", permission="update") def _update(request): """If activity is not completely synced. Than sync it when opening""" item = get_item_from_request(request) if not item.has_streams:
nlog = Estimatelog() nlog.estimate = sprint.estimate nlog.date = datetime.date.today() sprint.estimatelog.append(nlog) return task def update_callback(request, task): #for ptask in task.get_parents(): # _add_estimatelog(ptask) #else: # _add_estimatelog(task) _add_estimatelog(task) return task @view_config(route_name=get_action_routename(Task, 'create'), renderer='/default/create.mako', permission='create') def create_(request): return create(request, create_callback) @view_config(route_name=get_action_routename(Task, 'update'), renderer='/default/update.mako', permission='update') def update_(request): return update(request, update_callback) @view_config(route_name=get_action_routename(Task, 'delete'), renderer='/default/confirm.mako', permission='delete') def delete_(request):
import logging from pyramid.view import view_config from ringo.lib.helpers import get_action_routename from ringo.lib.form import get_path_to_form_config from ringo.views.base import create from ringo.model.form import Form log = logging.getLogger(__name__) def load_config(path): data = "" with open(path) as f: data = f.read() return data @view_config(route_name=get_action_routename(Form, 'create'), renderer='/default/create.mako', permission='create') def create_(request): clazz = request.context.__model__ factory = clazz.get_item_factory() form = factory.create(request.user, values={}) definition = load_config( get_path_to_form_config("blobform_template.xml", "ringo")) form.definition = definition request.context.item = form return create(request)
from pyramid.view import view_config from ringo.lib.helpers import get_action_routename from ringo.views.request import ( handle_history, get_item_from_request, get_return_value ) from plorma.model.sprint import Sprint @view_config(route_name=get_action_routename(Sprint, 'board'), renderer='/sprint/board.mako', permission='read') def board(request): handle_history(request) rvalues = get_return_value(request) return rvalues
""" # A news item will be shown for all users in item.users. To make it # read we remove the entry of the current user from the item.users # list. PLEASE NOTE that simply removing the user from the list # using the "remove()" method on the item.users does not work as # expected so we need to rebuild the list of users here. users = [user for user in item.users if user.id != request.user.id] item.users = users return item def read_callback(request, item): """Callback which is called right after the news item has been loaded. :request: current request :item: the news item :returns: news item """ item = _mark_news_as_read(request, item) return item @view_config(route_name=get_action_routename(News, 'markasread', prefix="rest"), renderer='json', request_method="PUT", permission='read') def rest_markasread(request): return rest_read(request, callback=read_callback)