Ejemplo n.º 1
0
	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
Ejemplo n.º 2
0
	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)
Ejemplo n.º 3
0
    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"))
Ejemplo n.º 4
0
	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
Ejemplo n.º 5
0
	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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
			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.