def validate(self, req, frm, storable): """ The validation function for forms generated from this itemdef. @param req: The current request @type req: L{modu.web.app.Request} @param frm: The current form @type frm: L{modu.util.form.FormNode} @param storable: The Storable instance associated with this form. @type storable: list(L{modu.persist.storable.Storable}) @return: True if valid @rtype: bool """ form_data = req.data[frm.name] if('referer' in frm): referer = frm['referer'].value else: referer = None if(frm.submit_button.value == form_data.get('cancel', None).value): if(referer): app.redirect(referer) else: app.redirect(req.get_path(req.prepath, 'listing', storable.get_table())) elif(frm.submit_button.value == form_data.get('delete', None).value): if(self.delete(req, frm, storable)): if(referer): app.redirect(referer) elif(self.config.get('hidden', False)): app.redirect(req.get_path(req.prepath)) else: app.redirect(req.get_path(req.prepath, 'listing', storable.get_table())) else: return False if(frm.submit_button.value != form_data.get('save', None).value): validator = frm.submit_button.attr('validator', None) if(callable(validator)): return validator(req, frm, storable) req.messages.report('error', "A custom submit button was used, but no validator function found.") return False else: # call validate hook on each field, return false if they do for field in frm: if(field in self and 'validator' in self[field]): validator = self[field]['validator'] if(validator): if not(validator(req, frm, storable)): return False else: if not(frm[field].validate(req, frm)): return False return True
def get_response(self, req): if(auth.has_basic(req)): user = auth.verify_basic(req) req.session.set_user(user) else: auth.request_basic(req) referrer = req.get('HTTP_REFERER') if not(referrer): referrer = req.get_path('/trac') app.redirect(referrer)
def prepare_login(self, req): """ Handle creation and display of a login page. @param req: the current request @type req: L{modu.web.app.Request} """ self.template = "admin-login.html.tmpl" login_form = user.get_default_login_form() if login_form.execute(req): app.redirect(req.get_path(req.path)) self.set_slot("login_form", login_form.render(req)) self.set_slot("title", self.options.get("login_title", "admin login"))
def delete(self, req, form, storable): """ The delete function for forms generated from this itemdef. @param req: The current request @type req: L{modu.web.app.Request} @param frm: The current form @type frm: L{modu.util.form.FormNode} @param storable: The Storable instance to delete. @type storable: list(L{modu.persist.storable.Storable}) @return: True if deleted @rtype: bool """ if not(self.deletable(req)): req.messages.report('error', "You are not allowed to delete `%s` records." % storable.get_table()) return False if('predelete_callback' in self.config): result = self.config['predelete_callback'](req, form, storable) if(result is False): return False deleted_id = storable.get_id() deleted_table = storable.get_table() storable.get_store().destroy(storable, self.config.get('delete_related_storables', False)) if('postdelete_callback' in self.config): self.config['postdelete_callback'](req, form, storable) req.messages.report('message', "Record #%d in %s was deleted." % (deleted_id, deleted_table)) if('referer' in form): referer = form['referer'].value else: referer = None app.redirect(referer) return True
def prepare_content(self, req): """ @see: L{modu.web.resource.IContent.prepare_content()} """ if not(req.postpath): app.redirect(req.get_path('/')) req.store.ensure_factory('blog', blog.Blog) try: blog_id = int(req.postpath[0]) except ValueError: b = req.store.load_one('blog', active=1, url_code=req.postpath[0]) else: b = req.store.load_one('blog', active=1, id=blog_id) if(b): app.redirect(req.get_path('blog', b.url_code), permanent=True) if(b is None): app.raise404(req.postpath[0]) self.set_slot('title', b.title) self.set_slot('blog', b)
def prepare_listing(self, req, itemdef): """ Handle creation and display of the listing page. @param req: the current request @type req: L{modu.web.app.Request} @param itemdef: the itemdef to use to generate the listing @type itemdef: L{modu.editable.define.itemdef} """ table_name = itemdef.config.get("table", itemdef.name) session_search_data = req.session.setdefault("search_form", {}).setdefault(itemdef.name, {}) # import pdb; pdb.set_trace() form_data = req.data.get("%s-search-form" % itemdef.name, {}) if isinstance(form_data, dict) and form_data.get("clear_search", None).value: req.session.setdefault("search_form", {})[itemdef.name] = {} app.redirect(req.get_path(req.prepath, "listing", itemdef.name)) # create a fake storable to make itemdef/form happy search_storable = storable.Storable(table_name) if "default_search" in itemdef.config: for k, v in itemdef.config["default_search"].items(): k = itemdef[k].get_column_name() setattr(search_storable, k, v) if session_search_data: for k, v in session_search_data.items(): if k in itemdef: k = itemdef[k].get_column_name() setattr(search_storable, k, v) # give it a factory so fields can use its store reference search_storable.set_factory(req.store.get_factory(table_name)) # build the form tree search_form = itemdef.get_search_form(req, search_storable) # this will make sure that if we're on a page other than 1, # a search submission will take us back to page 1 search_form(action=req.get_path(req.path)) order_by = itemdef.config.get("order_by", "id DESC") if "order" in req.data and re.match(r"^\w+$", req.data["order"].value): order_by = req.data["order"].value if "desc" in req.data and req.data["desc"].value: order_by += " DESC" search_attribs = {"__order_by": order_by} # search_attribs.update(itemdef.config.get('default_where', {})) # this function will call search_form.execute() search_params = self.get_search_params(req, itemdef, search_form) search_attribs.update(search_params) if req.postpath[0] == "listing": pager = page.Paginator(calc_found=req.app.config.get("admin_calc_found_rows", True)) if "page" in req.data: pager.page = int(req.data["page"].value) else: pager.page = 1 pager.per_page = itemdef.config.get("per_page", 25) items = pager.get_results(req.store, table_name, search_attribs) forms = itemdef.get_listing(req, items) thm = theme.Theme(req) if len(search_form): self.set_slot("search_form", search_form.render(req)) else: self.set_slot("search_form", "") self.set_slot("pager", pager) self.set_slot("page_guide", thm.page_guide(pager, req.get_path(req.path))) self.set_slot("forms", forms) self.set_slot("theme", thm) self.set_slot("selected_items", items) default_title = "Listing %s Records" % itemdef.name.title() custom_title = itemdef.config.get("listing_title", default_title) self.set_slot("title", tags.encode_htmlentities(custom_title)) template_variable_callback = itemdef.config.get("template_variable_callback") if callable(template_variable_callback): for key, value in template_variable_callback(req, forms, search_storable).items(): self.set_slot(key, value) self.template = itemdef.config.get("list_template", "admin-listing.html.tmpl") elif req.postpath[0] == "export": if callable(itemdef.config.get("export_query_builder")): data = itemdef.config["export_query_builder"](req, itemdef, search_attribs) else: data = search_attribs items = req.store.load(table_name, data) self.prepare_export(req, itemdef, items)
def prepare_content(self, req): """ @see: L{modu.web.resource.IContent.prepare_content()} """ req.content.report( "header", tags.style(type="text/css")["@import '%s';" % req.get_path("assets", "admin-styles.css")] ) site_stylesheet = getattr(req.app, "admin_site_stylesheet", None) if callable(site_stylesheet): site_stylesheet = site_stylesheet(req) if site_stylesheet: req.content.report("header", tags.style(type="text/css")["@import '%s';" % site_stylesheet]) user = req["modu.user"] if user and user.get_id(): if req.postpath and req.postpath[0] == "logout": req.session.set_user(None) if "auth_redirect" in req.session: del req.session["auth_redirect"] app.redirect(req.get_path(req.prepath)) itemdefs = define.get_itemdefs(module_list=self.options.get("itemdef_module", None)) # get_itemdef_layout adds some data and clones the itemdef self.itemdef_layout = define.get_itemdef_layout(req, itemdefs) # FIXME: This is inelegant -- we find the current itemdef # by using itemdefs.get(req.postpath[1]), so we recreate # the itemdef list from the itemdef layout to stop # malicious URL access. # TODO: Limit the itemdefs by user *first*, then modify # get_itemdef_layout() to organize, but not limit. if self.itemdef_layout: itemdefs = dict( [(itemdef.name, itemdef) for itemdef in reduce(lambda x, y: x + y, self.itemdef_layout.values())] ) else: itemdefs = {} self.set_slot("itemdef_layout", self.itemdef_layout) if len(req.postpath) > 1: if req.postpath[0] == "custom": itemdef_name = "/".join(req.postpath[1:]) if itemdef_name not in itemdefs: itemdef_name = req.postpath[1] else: itemdef_name = req.postpath[1] # we just need to select the right itemdef selected_itemdef = itemdefs.get(itemdef_name) self.set_slot("selected_itemdef", selected_itemdef) if selected_itemdef is not None: configure_store(req, selected_itemdef) if req.postpath[0] == "detail": self.prepare_detail(req, selected_itemdef) elif req.postpath[0] == "autocomplete": self.prepare_autocomplete(req, selected_itemdef) elif req.postpath[0] == "custom": self.prepare_custom(req, selected_itemdef) elif req.postpath[0] in ("listing", "export") and not selected_itemdef.config.get("hidden", False): self.prepare_listing(req, selected_itemdef) else: app.raise404() else: app.raise403() else: default_path = self.options.get("default_path") if callable(default_path): default_path = default_path(req) if default_path: redirect_path = req.get_path(default_path) app.redirect(redirect_path) app.raise404("There is no item list at the path: %s" % req["REQUEST_URI"]) else: self.set_slot("itemdef_layout", None) self.set_slot("selected_itemdef", None) self.prepare_login(req)
postwrite_callback = self.config['postwrite_callback'] if not(isinstance(postwrite_callback, (list, tuple))): postwrite_callback = [postwrite_callback] for callback in postwrite_callback: if not(callback(req, form, storable)): postwrite_succeeded = False if(postwrite_succeeded): req.messages.report('message', 'Your changes to %s record #%s have been saved.' % (storable.get_table(), storable.get_id())) if('referer' in form): referer = form['referer'].value else: referer = None if(referer): app.redirect(referer) else: req.messages.report('error', 'There was an error in the postwrite process, but primary record data was saved.') return postwrite_succeeded def deletable(self, req): allow_delete = True if('delete_acl' in self.config): allow_delete = req.user.is_allowed(self.config['delete_acl']) return allow_delete and not self.config.get('no_delete', False) def delete(self, req, form, storable): """ The delete function for forms generated from this itemdef.