# HG changeset patch # User sylvain.thenault@logilab.fr # Date 1240938877 -7200 # Node ID 47b2ffbee760a64b7fc6e1d7f5c2bf7dbd44d396 # Parent 973c5f1dfad4ca2897b00ba1d954a8b6c591c5da# Parent 54fc5cc522109b4574a6550f15449e4d20dd3f73 backport default branch diff -r 973c5f1dfad4 -r 47b2ffbee760 i18n/en.po diff -r 973c5f1dfad4 -r 47b2ffbee760 i18n/es.po diff -r 973c5f1dfad4 -r 47b2ffbee760 i18n/fr.po diff -r 973c5f1dfad4 -r 47b2ffbee760 schemaviewer.py --- a/schemaviewer.py Tue Apr 28 19:12:52 2009 +0200 +++ b/schemaviewer.py Tue Apr 28 19:14:37 2009 +0200 @@ -157,7 +157,7 @@ return layout _ = self.req._ if self.req.user.matching_groups('managers'): - layout.append(self.format_acls(eschema, ('read', 'add', 'delete', 'update'))) + # layout.append(self.format_acls(eschema, ('read', 'add', 'delete', 'update'))) # possible views for this entity type views = [_(view.title) for view in self.possible_views(etype)] layout.append(Section(children=(Table(cols=1, rheaders=1, diff -r 973c5f1dfad4 -r 47b2ffbee760 server/sources/rql2sql.py --- a/server/sources/rql2sql.py Tue Apr 28 19:12:52 2009 +0200 +++ b/server/sources/rql2sql.py Tue Apr 28 19:14:37 2009 +0200 @@ -951,6 +951,8 @@ if rel is not None: rel._q_needcast = value return self.keyword_map[value]() + if constant.type == 'Boolean': + value = self.dbms_helper.boolean_value(value) if constant.type == 'Substitute': _id = constant.value if isinstance(_id, unicode): diff -r 973c5f1dfad4 -r 47b2ffbee760 web/data/cubicweb.acl.css --- a/web/data/cubicweb.acl.css Tue Apr 28 19:12:52 2009 +0200 +++ b/web/data/cubicweb.acl.css Tue Apr 28 19:14:37 2009 +0200 @@ -9,19 +9,90 @@ /* security edition form (views/management.py) */ /******************************************************************************/ +h2.schema{ + background : #ff7700; + color: #fff; + font-weight: bold; + padding : 0.1em 0.3em; +} + + +h3.schema{ + font-weight: bold; +} + +h4 a, +h4 a:link, +h4 a:visited{ + color:#000; + } + table.schemaInfo { - margin: 1ex 1em; + margin: 1em 0em; text-align: left; border: 1px solid black; border-collapse: collapse; + width:100%; } table.schemaInfo th, table.schemaInfo td { - padding: 0em 1em; - border: 1px solid black; + padding: .3em .5em; + border: 1px solid grey; + width:33%; +} + + +table.schemaInfo tr th { + padding: 0.2em 0px 0.2em 5px; + background-image:none; + background-color:#dfdfdf; +} + +table.schemaInfo thead tr { + border: 1px solid #dfdfdf; +} + +table.schemaInfo td { + padding: 3px 10px 3px 5px; + } +.users{ + color : #00CC33; + font-weight: bold } + +.guests{ + color : #ff7700; + font-weight: bold; +} + +.staff{ + color : #0083ab; + font-weight: bold; +} + +.owners{ + color : #8b0000; + font-weight: bold; +} + +.discret, +a.grey{ + color:#666; +} + +a.grey:hover{ + color:#000; +} + +.red{ + color : #ff7700; + } + +div#schema_security{ + width:780px; + } /******************************************************************************/ /* user groups edition form (views/euser.py) */ /******************************************************************************/ diff -r 973c5f1dfad4 -r 47b2ffbee760 web/data/external_resources --- a/web/data/external_resources Tue Apr 28 19:12:52 2009 +0200 +++ b/web/data/external_resources Tue Apr 28 19:14:37 2009 +0200 @@ -52,3 +52,4 @@ DOWNLOAD_ICON = DATADIR/download.gif UPLOAD_ICON = DATADIR/upload.gif GMARKER_ICON = DATADIR/gmap_blue_marker.png +UP_ICON = DATADIR/up.gif diff -r 973c5f1dfad4 -r 47b2ffbee760 web/data/up.gif Binary file web/data/up.gif has changed diff -r 973c5f1dfad4 -r 47b2ffbee760 web/views/management.py --- a/web/views/management.py Tue Apr 28 19:12:52 2009 +0200 +++ b/web/views/management.py Tue Apr 28 19:14:37 2009 +0200 @@ -22,8 +22,47 @@ SUBMIT_MSGID = _('Submit bug report') MAIL_SUBMIT_MSGID = _('Submit bug report by mail') +class SecurityViewMixIn(object): + """display security information for a given schema """ + def schema_definition(self, eschema, link=True, access_types=None): + w = self.w + _ = self.req._ + if not access_types: + access_types = eschema.ACTIONS + w(u'') + w(u'' % ( + _("permission"), _('granted to groups'), _('rql expressions'))) + for access_type in access_types: + w(u'') + w(u'' % _('%s_perm' % access_type)) + groups = eschema.get_groups(access_type) + l = [] + groups = [(_(group), group) for group in groups] + for trad, group in sorted(groups): + if link: + l.append(u'%s
' % ( + self.build_url('egroup/%s' % group), group, trad)) + else: + l.append(u'
%s
' % (group, trad)) + w(u'' % u''.join(l)) + rqlexprs = eschema.get_rqlexprs(access_type) + w(u'' % u'

'.join(expr.expression for expr in rqlexprs)) + w(u'\n') + w(u'
%s%s%s
%s%s%s
') -class SecurityManagementView(EntityView): + def has_schema_modified_permissions(self, eschema, access_types): + """ return True if eschema's actual permissions are diffrents + from the default ones + """ + for access_type in access_types: + if eschema.get_rqlexprs(access_type): + return True + if eschema.get_groups(access_type) != \ + frozenset(eschema.get_default_groups()[access_type]): + return True + return False + +class SecurityManagementView(EntityView, SecurityViewMixIn): """display security information for a given entity""" id = 'security' title = _('security') @@ -40,7 +79,7 @@ html_escape(entity.dc_title()))) # first show permissions defined by the schema self.w('

%s

' % _('schema\'s permissions definitions')) - self.schema_definition(entity) + self.schema_definition(entity.e_schema) self.w('

%s

' % _('manage security')) # ownership information if self.schema.rschema('owned_by').has_perm(self.req, 'add', @@ -56,26 +95,6 @@ if reqpermschema.has_perm(self.req, 'add', fromeid=entity.eid): self.require_permission_edit_form(entity) - def schema_definition(self, entity): - w = self.w - _ = self.req._ - w(u'') - w(u'' % ( - _("access type"), _('granted to groups'), _('rql expressions'))) - for access_type in ('read', 'add', 'update', 'delete'): - w(u'') - w(u'' % self.req.__('%s_permission' % access_type)) - groups = entity.e_schema.get_groups(access_type) - l = [] - for group in groups: - l.append(u'%s' % ( - self.build_url('egroup/%s' % group), _(group))) - w(u'' % u', '.join(l)) - rqlexprs = entity.e_schema.get_rqlexprs(access_type) - w(u'' % u'
'.join(expr.expression for expr in rqlexprs)) - w(u'\n') - w(u'
%s%s%s
%s%s%s
') - def owned_by_edit_form(self, entity): self.w('

%s

' % self.req._('ownership')) msg = self.req._('ownerships have been changed') diff -r 973c5f1dfad4 -r 47b2ffbee760 web/views/startup.py --- a/web/views/startup.py Tue Apr 28 19:12:52 2009 +0200 +++ b/web/views/startup.py Tue Apr 28 19:14:37 2009 +0200 @@ -10,10 +10,12 @@ from logilab.common.textutils import unormalize from logilab.mtconverter import html_escape -from cubicweb.view import StartupView -from cubicweb.common.uilib import ureport_as_html, ajax_replace_url +from cubicweb.common.uilib import ureport_as_html, unormalize, ajax_replace_url +from cubicweb.common.view import StartupView +from cubicweb.common.selectors import match_user_group from cubicweb.web.httpcache import EtagHTTPCacheManager - +from cubicweb.web.views.management import SecurityViewMixIn +from copy import deepcopy _ = unicode @@ -159,25 +161,135 @@ def call(self): """display schema information""" self.req.add_js('cubicweb.ajax.js') - self.req.add_css('cubicweb.schema.css') + self.req.add_css(('cubicweb.schema.css','cubicweb.acl.css')) withmeta = int(self.req.form.get('withmeta', 0)) + section = self.req.form.get('sec', '') self.w(u'%s\n' % ( html_escape(self.req.build_url('view', vid='schemagraph', withmeta=withmeta)), self.req._("graphical representation of the application'schema"))) if withmeta: self.w(u'
%s
' % ( - self.build_url('schema', withmeta=0), + html_escape(self.build_url('schema', withmeta=0, sec=section)), self.req._('hide meta-data'))) else: self.w(u'
%s
' % ( - self.build_url('schema', withmeta=1), + html_escape(self.build_url('schema', withmeta=1, sec=section)), self.req._('show meta-data'))) - self.w(u'
%s
' % + self.w(u'%s
' % (html_escape(ajax_replace_url('detailed_schema', '', 'schematext', skipmeta=int(not withmeta))), self.req._('detailed schema view'))) + if self.req.user.matching_groups('managers'): + self.w(u'%s' % + (html_escape(ajax_replace_url('detailed_schema', '', 'schema_security', + skipmeta=int(not withmeta))), + self.req._('security'))) + self.w(u'
') + if section: + self.wview(section, None) + self.w(u'
') + + +class ManagerSchemaPermissionsView(StartupView, SecurityViewMixIn): + id = 'schema_security' + require_groups = ('managers',) + __selectors__ = StartupView.__selectors__ + (match_user_group,) + + def call(self, display_relations=True, + skiprels=('is', 'is_instance_of', 'identity', 'owned_by', 'created_by')): + _ = self.req._ + formparams = {} + formparams['sec'] = self.id + formparams['withmeta'] = int(self.req.form.get('withmeta', True)) + schema = self.schema + # compute entities + entities = [eschema for eschema in schema.entities() + if not eschema.is_final()] + if not formparams['withmeta']: + entities = [eschema for eschema in entities + if not eschema.meta] + # compute relations + relations = [] + if display_relations: + relations = [rschema for rschema in schema.relations() + if not (rschema.is_final() or rschema.type in skiprels)] + if not formparams['withmeta']: + relations = [rschema for rschema in relations + if not rschema.meta] + # index + self.w(u'
') + self.w(u'

%s

' % _('index').capitalize()) + self.w(u'

%s

' % _('Entities').capitalize()) + ents = [] + for eschema in sorted(entities): + url = html_escape(self.build_url('schema', **formparams) + '#' + eschema.type) + ents.append(u'
%s (%s)' % (url, eschema.type, _(eschema.type))) + self.w('%s' % ', '.join(ents)) + self.w(u'

%s

' % (_('relations').capitalize())) + rels = [] + for eschema in sorted(relations): + url = html_escape(self.build_url('schema', **formparams) + '#' + eschema.type) + rels.append(u'%s (%s), ' % (url , eschema.type, _(eschema.type))) + self.w('%s' % ', '.join(ents)) + # entities + self.display_entities(entities, formparams) + # relations + if relations: + self.display_relations(relations, formparams) + self.w(u'
') + + def display_entities(self, entities, formparams): + _ = self.req._ + self.w(u'') + self.w(u'

%s

' % _('permissions for entities').capitalize()) + for eschema in sorted(entities): + self.w(u'
' % (eschema.type, eschema.type)) + self.w(u'

%s (%s) ' % (eschema.type, _(eschema.type))) + url = html_escape(self.build_url('schema', **formparams) + '#index') + self.w(u'%s' % (url, self.req.external_resource('UP_ICON'), _('up'))) + self.w(u'

') + self.w(u'
') + self.schema_definition(eschema, link=False) + + # display entity attributes only if they have some permissions modified + modified_attrs = [] + for attr, etype in eschema.attribute_definitions(): + if self.has_schema_modified_permissions(attr, attr.ACTIONS): + modified_attrs.append(attr) + if modified_attrs: + self.w(u'

%s

' % _('attributes with modified permissions:').capitalize()) + self.w(u'
') + self.w(u'
') + for attr in modified_attrs: + self.w(u'

%s (%s)

' % (attr.type, _(attr.type))) + self.schema_definition(attr, link=False) + self.w(u'
') + else: + self.w(u'') + def display_relations(self, relations, formparams): + _ = self.req._ + self.w(u'') + self.w(u'

%s

' % _('permissions for relations').capitalize()) + for rschema in sorted(relations): + self.w(u'
' % (rschema.type, rschema.type)) + self.w(u'

%s (%s) ' % (rschema.type, _(rschema.type))) + url = html_escape(self.build_url('schema', **formparams) + '#index') + self.w(u'%s' % (url, self.req.external_resource('UP_ICON'), _('up'))) + self.w(u'

') + self.w(u'
') + subjects = [str(subj) for subj in rschema.subjects()] + self.w(u'
%s %s (%s)
' % (_('subject_plural:'), + ', '.join( [str(subj) for subj in rschema.subjects()]), + ', '.join( [_(str(subj)) for subj in rschema.subjects()]))) + self.w(u'
%s %s (%s)
' % (_('object_plural:'), + ', '.join( [str(obj) for obj in rschema.objects()]), + ', '.join( [_(str(obj)) for obj in rschema.objects()]))) + self.schema_definition(rschema, link=False) + self.w(u'
') + + class SchemaUreportsView(StartupView): id = 'schematext'