r5792 - in branches/statusquo: cumin/python/cumin wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2013-12-20 16:45:58 +0000 (Fri, 20 Dec 2013)
New Revision: 5792
Modified:
branches/statusquo/cumin/python/cumin/parameters.py
branches/statusquo/cumin/python/cumin/widgets.py
branches/statusquo/wooly/python/wooly/server.py
Log:
Additional fix for BZ1015692
Modified: branches/statusquo/cumin/python/cumin/parameters.py
===================================================================
--- branches/statusquo/cumin/python/cumin/parameters.py 2013-12-20 16:43:39 UTC (rev 5791)
+++ branches/statusquo/cumin/python/cumin/parameters.py 2013-12-20 16:45:58 UTC (rev 5792)
@@ -10,6 +10,11 @@
return login.user
+ def set(self, session, value):
+ # Since we always redirect the user attribute to the
+ # login session on get, make it explicit that we do nothing here
+ return None
+
class CuminClassParameter(Parameter):
def do_unmarshal(self, string):
return getattr(self.app.model, string, None)
Modified: branches/statusquo/cumin/python/cumin/widgets.py
===================================================================
--- branches/statusquo/cumin/python/cumin/widgets.py 2013-12-20 16:43:39 UTC (rev 5791)
+++ branches/statusquo/cumin/python/cumin/widgets.py 2013-12-20 16:45:58 UTC (rev 5792)
@@ -1527,8 +1527,21 @@
for cls, package, agent in zip(classes, packages, agents):
rosemary_package = self.app.model._packages_by_name[package]
rosemary_cls = rosemary_package._classes_by_name[cls]
- objects.append(rosemary_cls.get_object(cursor, _qmf_object_id=agent))
+ obj = rosemary_cls.get_object(cursor, _qmf_object_id=agent)
+ if obj is None:
+ continue
+ # A more general solution may be needed here in the future to
+ # restrict objects during csv export. Currently, submissions are the only objects
+ # visible to the user role and they have an Owner field.
+ # Make sure the Owner matches the logged in user for each record.
+ # An admin role needs no restrictions.
+ if not self.app.authorizator.is_enforcing() or \
+ not cls in ["Submission"] or \
+ session.client_session.check_owner(obj.Owner, treat_admin_as_owner=True):
+ objects.append(obj)
+ else:
+ raise Exception("Error exporting CSV, current user does not own that!")
return objects
def get_file_name(self, session):
Modified: branches/statusquo/wooly/python/wooly/server.py
===================================================================
--- branches/statusquo/wooly/python/wooly/server.py 2013-12-20 16:43:39 UTC (rev 5791)
+++ branches/statusquo/wooly/python/wooly/server.py 2013-12-20 16:45:58 UTC (rev 5792)
@@ -377,9 +377,11 @@
self.attributes = dict()
- def check_owner(self, owner):
- user = self.attributes["login_session"].user.name
- return owner == user
+ def check_owner(self, owner, treat_admin_as_owner=False):
+ login = self.attributes["login_session"]
+ if owner != login.user.name:
+ return treat_admin_as_owner and "admin" in login.group
+ return True
def get_csrf(self):
return self.csrf
10 years, 4 months
r5791 - in branches/statusquo: cumin/python/cumin cumin/python/cumin/grid wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2013-12-20 16:43:39 +0000 (Fri, 20 Dec 2013)
New Revision: 5791
Modified:
branches/statusquo/cumin/python/cumin/grid/limit.py
branches/statusquo/cumin/python/cumin/grid/tags.py
branches/statusquo/cumin/python/cumin/model.py
branches/statusquo/cumin/python/cumin/objectselector.py
branches/statusquo/wooly/python/wooly/__init__.py
branches/statusquo/wooly/python/wooly/forms.py
branches/statusquo/wooly/python/wooly/server.py
Log:
Add a unified patch for
BZ1017425
BZ1017427
Modified: branches/statusquo/cumin/python/cumin/grid/limit.py
===================================================================
--- branches/statusquo/cumin/python/cumin/grid/limit.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/cumin/python/cumin/grid/limit.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -1,3 +1,4 @@
+from cumin.util import xml_escape
from cumin.formats import fmt_link
from cumin.objectframe import ObjectFrame, ObjectFrameTask, \
ObjectFrameTaskForm
@@ -18,11 +19,18 @@
log = logging.getLogger("cumin.limit")
LIMIT_FLOAT_VALUE_FOR_UNLIMITED = 1000000.0
+def _limit_max(limit_max):
+ try:
+ limit_max = float(limit_max)
+ if limit_max >= LIMIT_FLOAT_VALUE_FOR_UNLIMITED:
+ limit_max = "Unlimited"
+ except:
+ limit_max = 0
+ return limit_max
+
class LimitAdapter(ObjectQmfAdapter):
def get_negotiator(self, session):
- cls = self.app.model.com_redhat_grid.Negotiator
- negotiator = self.app.model.find_youngest(cls, session.cursor)
- return negotiator
+ return self.app.model.get_negotiator(session)
def get_count(self, values):
data = self.do_get_data(values)
@@ -72,7 +80,6 @@
negotiator = self.parent.adapter.get_negotiator(session)
self.frame.limit.id.set(session, negotiator._id)
self.frame.limit.set_limit.form.limit_name.set(session, limit_name)
- self.frame.limit.set_limit.form.limit_max.set(session, limit_max)
return limit_name
class UsageColumn(ObjectTableColumn):
@@ -90,12 +97,7 @@
def render_cell_content(self, session, data):
value = None
limit_max = super(LimitTable.MaxColumn, self).render_cell_content(session, data)
- try:
- limit_max = float(limit_max)
- if limit_max >= LIMIT_FLOAT_VALUE_FOR_UNLIMITED:
- limit_max = "Unlimited"
- except:
- limit_max = 0
+ limit_max = _limit_max(limit_max)
# if we are exporting csv, we don't want to return a link, so we check here
if session.page == self.app.export_page:
@@ -146,7 +148,6 @@
def do_enter(self, session, osession):
self.form.limit_name.set(session, self.form.limit_name.get(osession))
- self.form.limit_max.set(session, self.form.limit_max.get(osession))
def do_invoke(self, invoc, negotiator, limit_name, limit_max):
@@ -186,12 +187,35 @@
self.limit_max = self.LimitMax(app, "max")
self.limit_max.required = True
self.add_field(self.limit_max)
-
+
+ def do_process(self, session):
+ super(NegotiatorLimitForm, self).do_process(session)
+ neg = self.app.model.get_negotiator(session)
+ limits = self.app.model.get_negotiator_limits(neg)
+ try:
+ my_limit = limits.data[self.limit_name.get(session)]['MAX']
+ except:
+ my_limit = 0
+ self.limit_max.set(session, _limit_max(my_limit))
+
+ def _validate_limit_name(self, session):
+ value = self.limit_name.get(session)
+ message = None
+ if value:
+ neg = self.app.model.get_negotiator(session)
+ limits = self.app.model.get_negotiator_limits(neg)
+ if value not in limits.data:
+ message = "Limit '%s' does not exist, press Cancel" % value
+
+ if message:
+ self.errors.add(session, FormError(message))
+
def process_submit(self, session):
new_max_value = self.limit_max.input.get(session)
unlimited_check_value = self.limit_max.checkbox.param.get(session)
self.limit_max.validate(session)
+ self._validate_limit_name(session)
if not self.errors.get(session):
if new_max_value.lower() in ("unlimited", "na", "n/a") or float(new_max_value) >= LIMIT_FLOAT_VALUE_FOR_UNLIMITED:
self.limit_max.set(session, LIMIT_FLOAT_VALUE_FOR_UNLIMITED)
@@ -225,10 +249,10 @@
return writer.to_string()
def render_field_value(self,session):
- return self.input.get(session)
+ return xml_escape(self.input.get(session))
def render_field_name(self,session):
- return self.input.param.path
+ return xml_escape(self.input.param.path)
def render_is_readonly(self, session):
retval = ""
@@ -260,8 +284,8 @@
return "Limit name"
class DisabledInput(StringInput):
- # used to override html and css
- pass
+ def validate_on_unmarshal(self, param, value, session):
+ return True
class LimitMax(StringFieldWithCheckbox):
def render_title(self, session):
Modified: branches/statusquo/cumin/python/cumin/grid/tags.py
===================================================================
--- branches/statusquo/cumin/python/cumin/grid/tags.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/cumin/python/cumin/grid/tags.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -578,6 +578,10 @@
def render_form_class(self, session):
return " ".join((super(RemoveTags, self).render_form_class(session), "mform"))
+
+class DisabledInput(StringInput):
+ def validate_on_unmarshal(self, param, value, session):
+ return True
class EditNodeTagsForm(ObjectFrameTaskForm):
'''
@@ -679,7 +683,7 @@
def __init__(self, app, name):
super(EditNodeTagsForm.NodeName, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
def get(self,session):
@@ -689,14 +693,11 @@
def render_title(self, session):
return "Host name"
- class DisabledInput(StringInput):
- pass
-
class Tags(StringField):
def __init__(self, app, name):
super(EditNodeTagsForm.Tags, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
def render_title(self, session):
@@ -716,9 +717,6 @@
value = truncate_text(value, 50, True)
return value
- class DisabledInput(StringInput):
- pass
-
class EditTagNodesForm(ObjectFrameTaskForm):
'''
This form will allow the editing of nodes for a single given tag
@@ -728,24 +726,21 @@
self.tags = self.Tags(app, "tags")
self.add_field(self.tags)
-
+
self.node_name = self.NodeName(app, "node_name")
self.add_field(self.node_name)
-
+
self.possible_nodes = self.NodesList(app, "pnod")
self.add_field(self.possible_nodes)
self.update_enabled = False
-
-
+
def process_submit(self, session):
tag = self.tags.input.get(session)
nodes_value = self.possible_nodes.get(session)
self.tags.validate(session)
if not self.errors.get(session):
- self.tags.set(session, tag)
-
self.task.invoke(session, None, tag, nodes_value)
self.task.exit_with_redirect(session)
@@ -812,7 +807,7 @@
def __init__(self, app, name):
super(EditTagNodesForm.NodeName, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
def render_inputs(self, session, *args):
@@ -824,16 +819,26 @@
def render_title(self, session):
return "Current hosts"
-
- class DisabledInput(StringInput):
- pass
class Tags(StringField):
def __init__(self, app, name):
super(EditTagNodesForm.Tags, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
+
+ def validate(self, session):
+ # We don't want to create tags here, just edit an existing
+ # tag. So make sure it exists,
+ super(EditTagNodesForm.Tags, self).validate(session)
+ message = None
+ if not self.form.errors.get(session):
+ t = self.input.get(session)
+ if self.app.wallaby.get_tag_by_name(t) is None:
+ message = "Tag '%s' does not exist, press cancel" % t
+
+ if message:
+ self.form.errors.add(session, FormError(message))
def render_title(self, session):
return "Tag"
@@ -841,9 +846,6 @@
def get(self,session):
value = self.input.get(session)
return value
-
- class DisabledInput(StringInput):
- pass
class EditTagFeaturesForm(ObjectFrameTaskForm):
'''
@@ -862,8 +864,7 @@
self.add_field(self.possible_features)
self.update_enabled = False
-
-
+
def process_submit(self, session):
tag = self.tags.input.get(session)
features_value = self.possible_features.get(session)
@@ -931,7 +932,7 @@
def __init__(self, app, name):
super(EditTagFeaturesForm.FeatureName, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
def render_inputs(self, session, *args):
@@ -947,16 +948,24 @@
def render_title(self, session):
return "Current features"
-
- class DisabledInput(StringInput):
- pass
class Tags(StringField):
def __init__(self, app, name):
super(EditTagFeaturesForm.Tags, self).__init__(app, name)
- self.input = self.DisabledInput(app, "input")
+ self.input = DisabledInput(app, "input")
self.replace_child(self.input)
+
+ def validate(self, session):
+ super(EditTagFeaturesForm.Tags, self).validate(session)
+ message = None
+ if not self.form.errors.get(session):
+ t = self.input.get(session)
+ if self.app.wallaby.get_tag_by_name(t) is None:
+ message = "Tag '%s' does not exist, press cancel" % t
+
+ if message:
+ self.form.errors.add(session, FormError(message))
def render_title(self, session):
return "Tag"
@@ -964,9 +973,6 @@
def get(self,session):
value = self.input.get(session)
return value
-
- class DisabledInput(StringInput):
- pass
class TagsNodeEditTask(ObjectFrameTask):
'''
@@ -1020,12 +1026,6 @@
def do_enter(self, session, osession):
tag_id = osession.values_by_path["main.grid.tag.id"]
self.form.tags.set(session, tag_id)
-
- nodes = "No nodes currently assigned"
- node_list = self.app.wallaby.get_node_names(tag_id)
- if len(node_list) > 0:
- nodes = ", ".join(node_list)
- self.form.node_name.set(session, nodes)
def callback(self, result):
if result is not None:
@@ -1097,14 +1097,6 @@
def do_enter(self, session, osession):
tag_id = osession.values_by_path["main.grid.tag.id"]
self.form.tags.set(session, tag_id)
- features = "No features currently assigned"
- tag = self.app.wallaby.get_tag_by_name(tag_id)
- feature_list = list()
- if tag is not None:
- feature_list = tag.features
- if len(feature_list) > 0:
- features = ", ".join(feature_list)
- self.form.feature_name.set(session, features)
def callback(self, result):
if result == False:
Modified: branches/statusquo/cumin/python/cumin/model.py
===================================================================
--- branches/statusquo/cumin/python/cumin/model.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/cumin/python/cumin/model.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -249,9 +249,14 @@
return job_server
def get_scheduler_from_jobserver(self, session, job_server):
- cls = self.app.model.com_redhat_grid.Scheduler
+ cls = self.com_redhat_grid.Scheduler
return cls.get_object(session.cursor, _id=job_server._schedulerRef_id)
+ def get_negotiator(self, session):
+ cls = self.com_redhat_grid.Negotiator
+ negotiator = self.find_youngest(cls, session.cursor)
+ return negotiator
+
class CuminProperty(object):
def __init__(self, cls, name):
self.model = cls.model
Modified: branches/statusquo/cumin/python/cumin/objectselector.py
===================================================================
--- branches/statusquo/cumin/python/cumin/objectselector.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/cumin/python/cumin/objectselector.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -302,7 +302,7 @@
self.table.add_child(self.table.export)
def add_search_filter(self, this):
- search = StringInput(self.app, "search")
+ search = self.SearchInput(self.app, "search")
search.param.default = ""
search.title = "Search in %s column" % this.attr.title
@@ -310,7 +310,7 @@
self.filters.add_child(search)
def add_selectable_search_filter(self, inputSet):
- search = StringInput(self.app, "search")
+ search = self.SearchInput(self.app, "search")
search.param.default = ""
search.title = "Search in column"
search.size = 35
@@ -318,7 +318,6 @@
self.selectablefilters.add_child(search)
self.selectablefilters.add_child(inputSet)
-
def render_search_id(self, session):
if len(self.filters.children):
return self.filters.children[0].render_id(session)
@@ -350,6 +349,10 @@
def get_data_options(self, session):
return self.table.get_data_options(session)
+ class SearchInput(StringInput):
+ def validate_on_unmarshal(self, value, param, session):
+ return True
+
class ObjectSelectorTable(ObjectTable):
def __init__(self, app, name, cls):
super(ObjectSelectorTable, self).__init__(app, name, cls)
@@ -504,6 +507,11 @@
def render_select_box(self, session):
return self.parent.children_by_name['search'].path
+ def validate_on_unmarshal(self, param, value, session):
+ if param == self.operator_param:
+ return value in self.operator_selector.do_get_items(session)
+ return True
+
class SearchOperatorOptions(OptionInputSet):
def __init__(self, app, param):
super(SelectableSearchObjectTable.SearchFieldOptions.SearchOperatorOptions, self).__init__(app, "operator_input", param)
Modified: branches/statusquo/wooly/python/wooly/__init__.py
===================================================================
--- branches/statusquo/wooly/python/wooly/__init__.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/wooly/python/wooly/__init__.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -429,6 +429,9 @@
def get_redirect(self, session):
return self.page.redirect.get(session)
+ def validate_on_unmarshal(self, param, value, session):
+ return True
+
class Frame(Widget):
def show(self, session):
super(Frame, self).show(session)
@@ -942,6 +945,7 @@
unmarshal = classmethod(unmarshal)
def unmarshal_url_vars(self, string, separator=";"):
+ from wooly.forms import FormInput
vars = string.split(separator)
for var in vars:
@@ -954,9 +958,13 @@
value = unquote_plus(svalue)
param = self.page.get_page_parameter_by_path(key)
-
if param:
+ if not param.widget.validate_on_unmarshal(param, value, self):
+ # Don't try setting a form input anywhere other than
+ # the file stream of a POST request!
+ raise Exception("Illegal attempt to set parameter %s" % param)
param.add(self, param.unmarshal(value), key)
+
elif key == self.csrf_tag_name:
self.csrf_value = value
Modified: branches/statusquo/wooly/python/wooly/forms.py
===================================================================
--- branches/statusquo/wooly/python/wooly/forms.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/wooly/python/wooly/forms.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -129,6 +129,11 @@
def render_disabled_attr(self, session, *args):
return self.disabled and "disabled=\"disabled\"" or None
+ def validate_on_unmarshal(self, param, value, session):
+ # By default, disallow FormInputs except in a
+ # wsgi input stream for POST
+ return session.post
+
class MissingValueError(FormError):
def __init__(self, widget):
super(MissingValueError, self).__init__(None)
Modified: branches/statusquo/wooly/python/wooly/server.py
===================================================================
--- branches/statusquo/wooly/python/wooly/server.py 2013-12-20 16:40:19 UTC (rev 5790)
+++ branches/statusquo/wooly/python/wooly/server.py 2013-12-20 16:43:39 UTC (rev 5791)
@@ -219,11 +219,7 @@
def adapt_request_to_session(self, env, session):
- try:
- session.unmarshal_url_vars(env["QUERY_STRING"])
- except:
- # allow exceptions to pass so we can trap ReosmaryNotFound later
- pass
+ session.unmarshal_url_vars(env["QUERY_STRING"])
session.post = env["REQUEST_METHOD"] == "POST"
if session.post:
10 years, 4 months
r5790 - in branches/statusquo: cumin/python/cumin rosemary/python/rosemary
by tmckay@fedoraproject.org
Author: tmckay
Date: 2013-12-20 16:40:19 +0000 (Fri, 20 Dec 2013)
New Revision: 5790
Modified:
branches/statusquo/cumin/python/cumin/main.py
branches/statusquo/rosemary/python/rosemary/sqlfilter.py
Log:
Fixes BZ1022727
Modified: branches/statusquo/cumin/python/cumin/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/main.py 2013-12-20 16:37:53 UTC (rev 5789)
+++ branches/statusquo/cumin/python/cumin/main.py 2013-12-20 16:40:19 UTC (rev 5790)
@@ -542,9 +542,7 @@
self.adapter.vhost_id_field = ObjectSqlField \
(self.adapter, self.cls.vhostRef)
- filter = SqlComparisonFilter(self.cls.msgDepth.sql_column,
- "null",
- "is not")
+ filter = SqlNullFilter(self.cls.msgDepth.sql_column)
self.adapter.query.add_filter(filter)
def render_rows(self, session):
@@ -588,9 +586,7 @@
def init(self):
super(TopSystemTable, self).init()
- filter = SqlComparisonFilter(self.cls.loadAverage1Min.sql_column,
- "null",
- "is not")
+ filter = SqlNullFilter(self.cls.loadAverage1Min.sql_column)
self.adapter.query.add_filter(filter)
class TopSubmissionTable(TopTable):
Modified: branches/statusquo/rosemary/python/rosemary/sqlfilter.py
===================================================================
--- branches/statusquo/rosemary/python/rosemary/sqlfilter.py 2013-12-20 16:37:53 UTC (rev 5789)
+++ branches/statusquo/rosemary/python/rosemary/sqlfilter.py 2013-12-20 16:40:19 UTC (rev 5790)
@@ -5,7 +5,18 @@
class SqlFilter(object):
pass
-class SqlComparisonFilter(SqlFilter):
+class SqlOpFilter(SqlFilter):
+ def __init__(self, operator, *ops):
+ self.operator = operator
+ self.valid_operators = ops
+ self.check_operator()
+
+ def check_operator(self):
+ if self.valid_operators and not self.operator in self.valid_operators:
+ raise Exception("Operator '%s' is not in the valid set %s" %
+ (self.operator, self.valid_operators))
+
+class SqlComparisonFilter(SqlOpFilter):
'''
Emit a comparison filter for a SQL query.
@@ -32,16 +43,16 @@
def __init__(self, this, that,
operator="=",
gen_cursor=None,
- mogrify=(False,False,True)):
+ mogrify=(False,False,True),
+ valid_operators=("<",">","=","<=",">=")):
- super(SqlComparisonFilter, self).__init__()
+ super(SqlComparisonFilter, self).__init__(operator, *valid_operators)
assert isinstance(operator, str)
assert len(mogrify) == 3
self.this = getattr(this, "identifier", this)
self.that = getattr(that, "identifier", that)
- self.operator = operator
self.gen_cursor = gen_cursor
self.mogrify = mogrify
@@ -61,6 +72,7 @@
return cursor.mogrify(pattern, vals)
def emit(self):
+ self.check_operator()
if self.gen_cursor and True in self.mogrify:
return self._mogrify()
@@ -68,43 +80,50 @@
self.operator,
self.that)
+class SqlNullFilter(SqlComparisonFilter):
+ def __init__(self, this):
+ super(SqlNullFilter, self).__init__(this,
+ "null",
+ "is not",
+ valid_operators=("is not",))
+
class SqlValueFilter(SqlComparisonFilter):
- def __init__(self, this, operator="="):
+ def __init__(self, this, operator="=", valid_operators=("<",">","=","<=",">=")):
that = "%%(%s)s" % this.name
- super(SqlValueFilter, self).__init__(this, that, operator)
+ super(SqlValueFilter, self).__init__(this, that, operator,
+ valid_operators=valid_operators)
-class SqlExistenceFilter(SqlFilter):
- def __init__(self, subquery, operator="exists"):
- super(SqlExistenceFilter, self).__init__()
-
- self.subquery = subquery
- self.operator = operator
-
- def emit(self):
- return "%s (%s)" % (self.operator, self.subquery)
-
class SqlLikeFilter(SqlValueFilter):
BEGINS = "B"
CONTAINS = "C"
def __init__(self, this, operator="like"):
- super(SqlLikeFilter, self).__init__(this, operator)
+ super(SqlLikeFilter, self).__init__(this, operator, valid_operators=("like",))
class SqlILikeFilter(SqlValueFilter):
BEGINS = "B"
CONTAINS = "C"
def __init__(self, this, operator="ilike"):
- super(SqlILikeFilter, self).__init__(this, operator)
+ super(SqlILikeFilter, self).__init__(this, operator, valid_operators=("ilike",))
+class SqlExistenceFilter(SqlOpFilter):
+ def __init__(self, subquery, operator="exists"):
+ super(SqlExistenceFilter, self).__init__(operator, "exists")
-class SqlDateValueFilter(SqlFilter):
+ self.subquery = subquery
+
+ def emit(self):
+ self.check_operator()
+ return "%s (%s)" % (self.operator, self.subquery)
+
+class SqlDateValueFilter(SqlOpFilter):
def __init__(self, this, that, operator="="):
- super(SqlDateValueFilter, self).__init__()
+ super(SqlDateValueFilter, self).__init__(operator, "<",">","=","<=",">=")
assert isinstance(operator, str)
self.this = getattr(this, "identifier", this)
self.that = getattr(that, "identifier", that)
- self.operator = operator
def emit(self):
- return "%s %s date('%s')" % (self.this, self.operator, self.that)
\ No newline at end of file
+ self.check_operator()
+ return "%s %s date('%s')" % (self.this, self.operator, self.that)
10 years, 4 months
r5789 - in branches/statusquo: cumin/python/cumin cumin/python/cumin/grid cumin/python/cumin/inventory cumin/python/cumin/messaging cumin/python/cumin/usergrid wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2013-12-20 16:37:53 +0000 (Fri, 20 Dec 2013)
New Revision: 5789
Modified:
branches/statusquo/cumin/python/cumin/grid/main.py
branches/statusquo/cumin/python/cumin/grid/tags.py
branches/statusquo/cumin/python/cumin/inventory/main.py
branches/statusquo/cumin/python/cumin/main.py
branches/statusquo/cumin/python/cumin/messaging/main.py
branches/statusquo/cumin/python/cumin/objectselector.py
branches/statusquo/cumin/python/cumin/persona.py
branches/statusquo/cumin/python/cumin/stat.py
branches/statusquo/cumin/python/cumin/usergrid/main.py
branches/statusquo/cumin/python/cumin/widgets.py
branches/statusquo/wooly/python/wooly/__init__.py
Log:
Add a unified patch for the following issues
BZ1015692
BZ1015694
BZ1025227
Modified: branches/statusquo/cumin/python/cumin/grid/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/grid/main.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/grid/main.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -19,16 +19,28 @@
self.job_submit = JobSubmit(app)
self.dag_job_submit = DagJobSubmit(app)
self.vm_job_submit = VmJobSubmit(app)
+
+ def add_module_for_submits(self, module):
+ # Well, none of these are actually contained by
+ # anything per se and they are linked to via TaskLink
+ # objects from multiple places in grid and usergrid.
+ # Allow module values to be added...
+ for s in (self.job_submit,
+ self.dag_job_submit,
+ self.vm_job_submit):
+ if not hasattr(s.form, "cumin_module"):
+ s.form.cumin_module = []
+ s.form.cumin_module.append(module)
+
def init(self):
super(Module, self).init()
+ self.app.export_page.set_cumin_module_for_children(self.name)
self.frame = PoolFrame(self.app, "grid")
self.frame.cumin_module = self.name
+ self.add_module_for_submits(self.name)
+ self.app.main_page.add_to_view(self.frame)
- self.app.main_page.main.grid = self.frame
- self.app.main_page.main.add_tab(self.frame)
-
-
def init_test(self, test):
GridTest("grid", test)
Modified: branches/statusquo/cumin/python/cumin/grid/tags.py
===================================================================
--- branches/statusquo/cumin/python/cumin/grid/tags.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/grid/tags.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -301,11 +301,11 @@
super(TagInventory, self).__init__(app, name, cls)
self.table.adapter = TagsAdapter(app, cls)
- tag_add_task = AddTags(app)
+ tag_add_task = AddTags(app, self)
link = TaskLink(app, "tag_add", tag_add_task)
self.links.add_child(link)
- self.activate_config_task = ActivateConfigTask(app)
+ self.activate_config_task = ActivateConfigTask(app, self)
link = TaskLink(app, "actlink", self.activate_config_task)
self.links.add_child(link)
@@ -444,7 +444,7 @@
self.label = self.LabelField(app, "labelf")
self.add_field(self.label)
-
+
def render_submit_content(self, session):
''' overriding base method to control the label on the submit button '''
return "Activate"
@@ -1130,11 +1130,12 @@
'''
This task is used to activate the wallaby configuration.
'''
- def __init__(self, app):
+ def __init__(self, app, selector):
super(ActivateConfigTask, self).__init__(app)
cls = app.model.com_redhat_cumin_grid.Node
self.form = ActivateConfigurationForm(app, self.name, self, cls)
self.invoc = None
+ self.selector = selector
def get_title(self, session, object):
return "Activate wallaby configuration"
@@ -1157,11 +1158,12 @@
'''
This task is used to create a tag in wallaby without assigning it to any nodes.
'''
- def __init__(self, app):
+ def __init__(self, app, selector):
super(AddTags, self).__init__(app)
cls = app.model.com_redhat_cumin_grid.Node
self.form = CreateTags(app, self.name, self, cls)
self.invoc = None
+ self.selector = selector
def get_title(self, session, object):
return "Create tags"
Modified: branches/statusquo/cumin/python/cumin/inventory/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/inventory/main.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/inventory/main.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -14,6 +14,7 @@
def __init__(self, app, name):
super(Module, self).__init__(app, name)
+ self.app.export_page.set_cumin_module_for_children(self.name)
self.frame = InventoryFrame(app, "inventory")
self.app = app
self.frame.cumin_module = name
Modified: branches/statusquo/cumin/python/cumin/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/main.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/main.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -151,7 +151,9 @@
self.form_page = CuminFormPage(self, "form.html")
self.add_page(self.form_page)
- self.add_page(StatFlashPage(self, "chart.json"))
+ self.chart_page = StatFlashPage(self, "chart.json")
+ self.add_page(self.chart_page)
+
self.add_page(FlashFullPage(self, "flashpage.html"))
self.export_page = CuminExportPage(self, "csv")
@@ -279,6 +281,13 @@
super(Cumin, self).init()
+ # Form widgets need cumin_module values set for them
+ # because the links are processed directly by the forms page
+ # via the 'mode' parameter
+ self.form_page.set_modules_for_forms()
+
+ self.chart_page.set_modules_for_charts()
+
def start(self):
log.info("Starting %s", self)
@@ -365,10 +374,24 @@
self.main = main_view
self.add_mode(self.main)
self.set_default_frame(self.main)
- self.cumin_module = ["messaging", "grid"]
+ self.cumin_module = []
self.page_html_class = "Cumin"
+ def add_module(self, module):
+ if type(module) in (list, tuple):
+ self.cumin_module.extend(module)
+ else:
+ self.cumin_module.append(module)
+
+ def add_to_view(self, frame):
+ # Add a frame to the main view with a tab and
+ # make sure that the page is visible to the
+ # module associated with the frame
+ setattr(self.main, frame.name, frame)
+ self.main.add_tab(frame)
+ self.add_module(frame.cumin_module)
+
def render_title(self, session):
return self.get_title(session)
Modified: branches/statusquo/cumin/python/cumin/messaging/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/messaging/main.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/messaging/main.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -15,14 +15,14 @@
def __init__(self, app, name):
super(Module, self).__init__(app, name)
+ self.app.export_page.set_cumin_module_for_children(self.name)
self.frame = MessagingFrame(self.app, "messaging")
self.frame.cumin_module = name
def init(self):
super(Module, self).init()
- self.app.main_page.main.messaging = self.frame
- self.app.main_page.main.add_tab(self.frame)
+ self.app.main_page.add_to_view(self.frame)
def init_test(self, test):
MessagingTest("messaging", test)
Modified: branches/statusquo/cumin/python/cumin/objectselector.py
===================================================================
--- branches/statusquo/cumin/python/cumin/objectselector.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/objectselector.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -135,9 +135,11 @@
# avoid name collisions on csv page
while self.name in self.app.export_page.modes.children_by_name:
self.name = self.name + ".1"
+
+ # this will also set cumin_module on self to the
+ # prevailing value in effect for the page at this time
+ self.app.export_page.add_csv_exporter(self)
- self.app.export_page.modes.add_mode(self)
-
def render(self, session):
writer = Writer()
Modified: branches/statusquo/cumin/python/cumin/persona.py
===================================================================
--- branches/statusquo/cumin/python/cumin/persona.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/persona.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -129,7 +129,7 @@
return True
return False
- def authorize(self, web_session, widget):
+ def authorize(self, web_session, widget, reason_on_fail=None):
if not hasattr(widget, "cumin_module") or \
widget.cumin_module is None:
# no module for this widget, we have to allow it
@@ -141,29 +141,31 @@
# (like a column in a table that is only valid if a
# particular module has been loaded).
if type(widget.cumin_module) in (list, tuple):
- if len(set(widget.cumin_module) & set(self.persona.modules)) == 0:
- return False
- elif not widget.cumin_module in self.persona.modules:
- return False
+ res = len(set(widget.cumin_module) & set(self.persona.modules)) != 0
+ else:
+ res = widget.cumin_module in self.persona.modules
+ if not res:
+ reason = "MODULE_NOT_LOADED"
- if not self.is_enforcing():
- # Auth checks against group are off.
- return True
-
- try:
- group = web_session.client_session.attributes['login_session'].group
- except KeyError:
- group = "nogroup"
-
- if type(group) == type([]):
+ # Okay, check access by groups if checks are on
+ elif self.is_enforcing():
+ try:
+ group = web_session.client_session.attributes['login_session'].group
+ except KeyError:
+ group = "nogroup"
+ if not type(group) in (tuple, list):
+ group = [group]
for g in group:
- if self.persona.lookup(g, widget.cumin_module):
+ res = self.persona.lookup(g, widget.cumin_module)
+ if res:
log.debug("Allowing %s authorization for %s ",
widget.cumin_module, group)
- return True
- else:
- return self.persona.lookup(group, widget.cumin_module)
+ break
+ if not res:
+ log.debug("Denying %s authorization for %s ", widget.my_name, group)
+ reason = "GROUP_NOT_AUTHORIZED"
- log.debug("Denying %s authorization for %s ", widget.my_name, group)
- return False
+ if not res and reason_on_fail is not None:
+ reason_on_fail.reason = reason
+ return res
Modified: branches/statusquo/cumin/python/cumin/stat.py
===================================================================
--- branches/statusquo/cumin/python/cumin/stat.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/stat.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -154,6 +154,10 @@
self.fullpageable = True
+ def init(self):
+ super(StatValueChart, self).init()
+ self.app.chart_page.add_chart(self)
+
def get_href_params(self, session):
object = self.object.get(session)
params = list()
@@ -1228,6 +1232,8 @@
def __init__(self, app, name):
super(StatFlashPage, self).__init__(app, name)
+ self.charts = dict()
+
# number of milliseconds since the last update
self.elapsed = Parameter(app, "elapsed")
self.elapsed.default = None
@@ -1290,6 +1296,17 @@
return "text/plain"
def do_render(self, session):
+ try:
+ chart_id = self.chart_id.get(session)
+ if self.charts[chart_id]:
+ chart = self.charts[chart_id]
+ if not self.app.authorize_cb(session, chart):
+ log.debug("Redirect on not authorized for chart %s" % chart)
+ self.redirect_on_not_authorized(session)
+ return
+ except Exception, e:
+ pass
+
adapter, stats = self.get_adapter_stats(session)
chart = self.chart_factory(self.chart_type.get(session))
@@ -1311,6 +1328,25 @@
return chart_obj
+ def add_chart(self, chart):
+ self.charts[chart.path] = chart
+
+ def set_modules_for_charts(self):
+
+ # Look through all of the chart widgets we have stored as children
+ # and attempt to trace through ancestors and find a cumin_module value
+ for k,child in self.charts.iteritems():
+ if hasattr(child, "cumin_module") and child.cumin_module:
+ continue
+
+ for anc in child.ancestors:
+ if hasattr(anc, "cumin_module") and anc.cumin_module:
+ child.cumin_module = anc.cumin_module
+ log.debug("Adding %s module for %s from %s" % (anc.cumin_module,
+ child.name,
+ anc))
+ break
+
class PercentAreaChart(AreaChart):
def get_max_min(self, session, stats, samples, time_span, end_seconds_ago):
max_val, min_val = super(PercentAreaChart, self).get_max_min(session, stats, samples, time_span, end_seconds_ago)
Modified: branches/statusquo/cumin/python/cumin/usergrid/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/usergrid/main.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/usergrid/main.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -9,6 +9,11 @@
def init(self):
super(Module, self).init()
+ self.app.export_page.set_cumin_module_for_children(self.name)
self.app.user_grid_page = MainPage(self.app, "usergrid.html")
self.app.add_page(self.app.user_grid_page, add_to_link_set=True)
self.app.user_grid_page.cumin_module = self.name
+
+ # Usergrid links explicitly to submit forms in the grid module.
+ # Add our module value here
+ self.app.grid.add_module_for_submits(self.name)
Modified: branches/statusquo/cumin/python/cumin/widgets.py
===================================================================
--- branches/statusquo/cumin/python/cumin/widgets.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/cumin/python/cumin/widgets.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -1417,6 +1417,36 @@
# for form in model tasks:
# self.add_mode(form)
+ def set_modules_for_forms(self):
+
+ # Look through all of the form widgets we have stored as children
+ # and attempt to trace through ancestors and find a cumin_module value
+ for child in self.modes.children:
+ if hasattr(child, "cumin_module") and child.cumin_module:
+ continue
+
+ if not hasattr(child, "cumin_module"):
+ if hasattr(child, "task") and hasattr(child.task, "frame"):
+ start = child.task.frame
+ elif hasattr(child, "task") and hasattr(child.task, "selector"):
+ start = child.task.selector
+ else:
+ start = child
+
+ if hasattr(start, "cumin_module") and start.cumin_module:
+ child.cumin_module = start.cumin_module
+ log.debug("Adding %s module for %s from %s" % (start.cumin_module,
+ child.name,
+ start))
+ elif start.ancestors:
+ for anc in start.ancestors:
+ if hasattr(anc, "cumin_module") and anc.cumin_module:
+ child.cumin_module = anc.cumin_module
+ log.debug("Adding %s module for %s from %s" % (anc.cumin_module,
+ child.name,
+ anc))
+ break
+
def render_content(self, session):
writer = Writer()
@@ -1455,11 +1485,26 @@
agent = Parameter(app, "qmf_obj_id")
self.agents = ListParameter(app, "agents", agent)
self.add_parameter(self.agents)
+ self.cumin_module_value = None
+ def set_cumin_module_for_children(self, module):
+ self.cumin_module_value = module
+
+ def add_csv_exporter(self, exporter):
+ self.modes.add_mode(exporter)
+ if (not hasattr(exporter, "cumin_module") or \
+ not exporter.cumin_module) and self.cumin_module_value:
+ exporter.cumin_module = self.cumin_module_value
+
def render_content(self, session, *args):
writer = Writer()
mode = self.modes.mode.get(session)
+ if not self.app.authorize_cb(session, mode):
+ log.debug("Redirect on not authorized for csv export %s" % mode.name)
+ self.redirect_on_not_authorized(session)
+ return
+
objects = self.get_objects(session)
for obj, mobj in zip(objects, mode.objects):
mobj.set(session, obj)
Modified: branches/statusquo/wooly/python/wooly/__init__.py
===================================================================
--- branches/statusquo/wooly/python/wooly/__init__.py 2013-12-20 16:33:21 UTC (rev 5788)
+++ branches/statusquo/wooly/python/wooly/__init__.py 2013-12-20 16:37:53 UTC (rev 5789)
@@ -296,8 +296,16 @@
def redirect_on_not_authorized(self, session):
# Give an opportunity to redirect to a valid page
# when a user is not authorized for this widget.
- pass
-
+ mainpage = self.app.mainpage_cb(session)
+ if mainpage in self.app.pages_by_name:
+ log.debug("Not authorized, redirecting to %s", mainpage)
+ page = self.app.pages_by_name[mainpage]
+ sess = Session(page)
+ if hasattr(self, "redirect"):
+ self.redirect.set(session, sess.marshal())
+ elif hasattr(self, "page"):
+ self.page.redirect.set(session, sess.marshal())
+
def authorized(self, session):
return session.login_current()
@@ -315,8 +323,17 @@
self.redirect_to_login(session)
return
- if not self.app.authorize_cb(session, self):
- self.redirect_on_not_authorized(session)
+ class Reason(object):
+ pass
+
+ reason = Reason()
+ if not self.app.authorize_cb(session, self, reason):
+ # It's possible that a widget is not authorized
+ # because its module is not loaded, in which case
+ # it should simply not draw (no redirect needed).
+ # So check the reason before we redirect.
+ if reason.reason == "GROUP_NOT_AUTHORIZED":
+ self.redirect_on_not_authorized(session)
else:
if self.update_enabled:
self.page.enable_update(session, self)
10 years, 4 months
r5788 - in branches/statusquo: cumin/bin cumin/python/cumin wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2013-12-20 16:33:21 +0000 (Fri, 20 Dec 2013)
New Revision: 5788
Modified:
branches/statusquo/cumin/bin/cumin-web
branches/statusquo/cumin/python/cumin/config.py
branches/statusquo/cumin/python/cumin/main.py
branches/statusquo/wooly/python/wooly/server.py
Log:
Allow configurable limit on uri length
BZ983134
Modified: branches/statusquo/cumin/bin/cumin-web
===================================================================
--- branches/statusquo/cumin/bin/cumin-web 2013-11-05 14:04:07 UTC (rev 5787)
+++ branches/statusquo/cumin/bin/cumin-web 2013-12-20 16:33:21 UTC (rev 5788)
@@ -219,6 +219,9 @@
set_ldap_configs(cumin, values)
set_kerberos_configs(cumin, values)
+ # Set max_uri to 0 for unlimited...
+ cumin.max_uri = values.max_uri
+
# Not used right now
#cumin.auth_create_ondemand = values.auth_create_ondemand
#cumin.auth_proxy = values.auth_proxy
Modified: branches/statusquo/cumin/python/cumin/config.py
===================================================================
--- branches/statusquo/cumin/python/cumin/config.py 2013-11-05 14:04:07 UTC (rev 5787)
+++ branches/statusquo/cumin/python/cumin/config.py 2013-12-20 16:33:21 UTC (rev 5788)
@@ -275,6 +275,11 @@
param = ConfigParameter(self, "force-html-doctype", bool)
param.default = False
+ # Undocumented. Server generates 414 errors if uri length
+ # is longer than this value. 0 means unlimited.
+ param = ConfigParameter(self, "max-uri", int)
+ param.default = 2048
+
class CuminDataConfigSection(BrokeredConfigSection):
def __init__(self, config, name, strict_section=False):
super(CuminDataConfigSection, self).__init__(config, name,
Modified: branches/statusquo/cumin/python/cumin/main.py
===================================================================
--- branches/statusquo/cumin/python/cumin/main.py 2013-11-05 14:04:07 UTC (rev 5787)
+++ branches/statusquo/cumin/python/cumin/main.py 2013-12-20 16:33:21 UTC (rev 5788)
@@ -118,6 +118,8 @@
self.wallaby_broker = None
self.wallaby_refresh = 60
+ self.max_uri = 2048
+
def server_alive(self):
return self.server.server_alive()
@@ -179,6 +181,8 @@
def init(self, schema_version_check=True):
log.info("Initializing %s", self)
+ self.server.max_uri = self.max_uri
+
# Do this initialization as late as possible so that
# the application can set config values.
self.authenticator = CuminAuthenticator(self)
Modified: branches/statusquo/wooly/python/wooly/server.py
===================================================================
--- branches/statusquo/wooly/python/wooly/server.py 2013-11-05 14:04:07 UTC (rev 5787)
+++ branches/statusquo/wooly/python/wooly/server.py 2013-12-20 16:33:21 UTC (rev 5788)
@@ -42,6 +42,7 @@
self.client_sessions_by_id = dict()
self.client_session_expire_thread = ClientSessionExpireThread(self)
self.stop_requested = False
+ self.max_uri = 0
def server_alive(self):
return self.dispatch_thread.isAlive()
@@ -96,17 +97,29 @@
return then
def service_request(self, env, response):
- msg = "Request %s %s" % (env["REQUEST_METHOD"], env["REQUEST_URI"])
- log.info(msg)
- page = self.get_page(env)
- if page and not self.stop_requested:
- status, headers, content = self.service_page_request(page, env)
- else:
- status = "404 Not Found"
+ url_len = len(env["REQUEST_URI"])
+ if self.max_uri and url_len > self.max_uri:
+ msg = "Request(%s) longer than max_uri(%s) %s %s ..." % \
+ (url_len, self.max_uri,
+ env["REQUEST_METHOD"], env["REQUEST_URI"][:64])
+
+ log.debug(msg)
+ status = "414 Request-URI too long"
headers = ()
content = ""
+ else:
+ msg = "Request %s %s" % (env["REQUEST_METHOD"], env["REQUEST_URI"])
+ log.info(msg)
+ page = self.get_page(env)
+ if page and not self.stop_requested:
+ status, headers, content = self.service_page_request(page, env)
+ else:
+ status = "404 Not Found"
+ headers = ()
+ content = ""
+
response(status, headers)
log.info("Response %s", status)
10 years, 4 months