web/views/management.py
changeset 602 1454282a8b45
parent 431 18b4dd650ef8
child 604 e85042d18b48
equal deleted inserted replaced
582:0260b3b71d71 602:1454282a8b45
    21 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
    21 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
    22 from cubicweb.web.widgets import StaticComboBoxWidget
    22 from cubicweb.web.widgets import StaticComboBoxWidget
    23 from cubicweb.web.form import FormMixIn
    23 from cubicweb.web.form import FormMixIn
    24 
    24 
    25 _ = unicode
    25 _ = unicode
    26             
    26 
    27 def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
    27 def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
    28     w(u'<form method="post" action="%s">\n' % entity.req.build_url('edit'))
    28     w(u'<form method="post" action="%s">\n' % entity.req.build_url('edit'))
    29     w(u'<fieldset>\n')
    29     w(u'<fieldset>\n')
    30     w(u'<input type="hidden" name="__redirectvid" value="%s"/>\n' % redirectvid)
    30     w(u'<input type="hidden" name="__redirectvid" value="%s"/>\n' % redirectvid)
    31     w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % (
    31     w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % (
    40 
    40 
    41 class SecurityManagementView(EntityView):
    41 class SecurityManagementView(EntityView):
    42     """display security information for a given entity"""
    42     """display security information for a given entity"""
    43     id = 'security'
    43     id = 'security'
    44     title = _('security')
    44     title = _('security')
    45         
    45 
    46     def cell_call(self, row, col):
    46     def cell_call(self, row, col):
    47         self.req.add_js('cubicweb.edition.js')            
    47         self.req.add_js('cubicweb.edition.js')
    48         self.req.add_css('cubicweb.acl.css')            
    48         self.req.add_css('cubicweb.acl.css')
    49         entity = self.entity(row, col)
    49         entity = self.entity(row, col)
    50         w = self.w
    50         w = self.w
    51         _ = self.req._
    51         _ = self.req._
    52         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
    52         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
    53           % (entity.dc_type().capitalize(),
    53           % (entity.dc_type().capitalize(),
    88             w(u'<td>%s</td>' % u', '.join(l))
    88             w(u'<td>%s</td>' % u', '.join(l))
    89             rqlexprs = entity.e_schema.get_rqlexprs(access_type)
    89             rqlexprs = entity.e_schema.get_rqlexprs(access_type)
    90             w(u'<td>%s</td>' % u'<br/>'.join(expr.expression for expr in rqlexprs))
    90             w(u'<td>%s</td>' % u'<br/>'.join(expr.expression for expr in rqlexprs))
    91             w(u'</tr>\n')
    91             w(u'</tr>\n')
    92         w(u'</table>')
    92         w(u'</table>')
    93         
    93 
    94     def owned_by_edit_form(self, entity):
    94     def owned_by_edit_form(self, entity):
    95         self.w('<h3>%s</h3>' % self.req._('ownership'))
    95         self.w('<h3>%s</h3>' % self.req._('ownership'))
    96         begin_form(self.w, entity, 'security', msg= _('ownerships have been changed'))
    96         begin_form(self.w, entity, 'security', msg= _('ownerships have been changed'))
    97         self.w(u'<table border="0">\n')
    97         self.w(u'<table border="0">\n')
    98         self.w(u'<tr><td>\n')
    98         self.w(u'<tr><td>\n')
   167             wdg = newperm.get_widget('name')
   167             wdg = newperm.get_widget('name')
   168         w(u'<tr><td>%s</td>\n' % wdg.edit_render(newperm))
   168         w(u'<tr><td>%s</td>\n' % wdg.edit_render(newperm))
   169         wdg = newperm.get_widget('label')
   169         wdg = newperm.get_widget('label')
   170         w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
   170         w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
   171         wdg = newperm.get_widget('require_group')
   171         wdg = newperm.get_widget('require_group')
   172         w(u'<td>%s</td>\n' % wdg.edit_render(newperm))            
   172         w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
   173         w(u'<td>%s</td></tr>\n' % self.button_ok())
   173         w(u'<td>%s</td></tr>\n' % self.button_ok())
   174         w(u'</table>')
   174         w(u'</table>')
   175         w(u'</fieldset></form>\n')
   175         w(u'</fieldset></form>\n')
   176 
   176 
   177     def button_ok(self):
   177     def button_ok(self):
   178         return (u'<input class="validateButton" type="submit" name="submit" value="%s"/>'
   178         return (u'<input class="validateButton" type="submit" name="submit" value="%s"/>'
   179                 % self.req._(stdmsgs.BUTTON_OK))
   179                 % self.req._(stdmsgs.BUTTON_OK))
   180 
   180 
   181         
   181 
   182 class ErrorView(AnyRsetView):
   182 class ErrorView(AnyRsetView):
   183     """default view when no result has been found"""
   183     """default view when no result has been found"""
   184     __selectors__ = (yes,)
   184     __selectors__ = (yes,)
   185     id = 'error'
   185     id = 'error'
   186     
   186 
   187     def page_title(self):
   187     def page_title(self):
   188         """returns a title according to the result set - used for the
   188         """returns a title according to the result set - used for the
   189         title in the HTML header
   189         title in the HTML header
   190         """
   190         """
   191         return self.req._('an error occured')
   191         return self.req._('an error occured')
   192 
   192 
   193     def call(self):
   193     def call(self):
   194         req = self.req.reset_headers()
   194         req = self.req.reset_headers()
   195         _ = req._
   195         _ = req._; w = self.w
   196         ex = req.data.get('ex')#_("unable to find exception information"))
   196         ex = req.data.get('ex')#_("unable to find exception information"))
   197         excinfo = req.data.get('excinfo')
   197         excinfo = req.data.get('excinfo')
   198         title = _('an error occured')
   198         title = _('an error occured')
   199         self.w(u'<h2>%s</h2>' % title)
   199         w(u'<h2>%s</h2>' % title)
   200         if 'errmsg' in req.data:
   200         if 'errmsg' in req.data:
   201             ex = req.data['errmsg']
   201             ex = req.data['errmsg']
   202             exclass = None
   202             exclass = None
   203         else:
   203         else:
   204             exclass = ex.__class__.__name__
   204             exclass = ex.__class__.__name__
   205             ex = exc_message(ex, req.encoding)
   205             ex = exc_message(ex, req.encoding)
   206         if excinfo is not None and self.config['print-traceback']:
   206         if excinfo is not None and self.config['print-traceback']:
   207             if exclass is None:
   207             if exclass is None:
   208                 self.w(u'<div class="tb">%s</div>'
   208                 w(u'<div class="tb">%s</div>'
   209                        % html_escape(ex).replace("\n","<br />"))
   209                        % html_escape(ex).replace("\n","<br />"))
   210             else:
   210             else:
   211                 self.w(u'<div class="tb">%s: %s</div>'
   211                 w(u'<div class="tb">%s: %s</div>'
   212                        % (exclass, html_escape(ex).replace("\n","<br />")))
   212                        % (exclass, html_escape(ex).replace("\n","<br />")))
   213             self.w(u'<hr />')
   213             w(u'<hr />')
   214             self.w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
   214             w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
   215         else:
   215         else:
   216             self.w(u'<div class="tb">%s</div>' % (html_escape(ex).replace("\n","<br />")))
   216             w(u'<div class="tb">%s</div>' % (html_escape(ex).replace("\n","<br />")))
   217         # if excinfo is not None, it's probably not a bug
   217         # if excinfo is not None, it's probably not a bug
   218         if excinfo is None:
   218         if excinfo is None:
   219             return
   219             return
   220         vcconf = self.config.vc_config()
   220         vcconf = self.config.vc_config()
   221         self.w(u"<div>")
   221         w(u"<div>")
   222         eversion = vcconf.get('cubicweb', _('no version information'))
   222         eversion = vcconf.get('cubicweb', _('no version information'))
   223         # NOTE: tuple wrapping needed since eversion is itself a tuple
   223         # NOTE: tuple wrapping needed since eversion is itself a tuple
   224         self.w(u"<b>CubicWeb version:</b> %s<br/>\n" % (eversion,))
   224         w(u"<b>CubicWeb version:</b> %s<br/>\n" % (eversion,))
   225         for pkg in self.config.cubes():
   225         for pkg in self.config.cubes():
   226             pkgversion = vcconf.get(pkg, _('no version information'))
   226             pkgversion = vcconf.get(pkg, _('no version information'))
   227             self.w(u"<b>Package %s version:</b> %s<br/>\n" % (pkg, pkgversion))
   227             w(u"<b>Package %s version:</b> %s<br/>\n" % (pkg, pkgversion))
   228         self.w(u"</div>")
   228         w(u"</div>")
   229         # creates a bug submission link if SUBMIT_URL is set
   229         # creates a bug submission link if SUBMIT_URL is set
   230         submiturl = self.config['submit-url']
   230         submiturl = self.config['submit-url']
   231         if submiturl:
   231         if submiturl:
   232             binfo = text_error_description(ex, excinfo, req, eversion,
   232             binfo = text_error_description(ex, excinfo, req, eversion,
   233                                            [(pkg, vcconf.get(pkg, _('no version information')))
   233                                            [(pkg, vcconf.get(pkg, _('no version information')))
   234                                             for pkg in self.config.cubes()])
   234                                             for pkg in self.config.cubes()])
   235             self.w(u'<form action="%s" method="post">\n' % html_escape(submiturl))
   235             w(u'<form action="%s" method="post">\n' % html_escape(submiturl))
   236             self.w(u'<fieldset>\n')
   236             w(u'<fieldset>\n')
   237             self.w(u'<textarea class="hidden" name="description">%s</textarea>' % html_escape(binfo))
   237             w(u'<textarea class="hidden" name="description">%s</textarea>' % html_escape(binfo))
   238             self.w(u'<input type="hidden" name="description_format" value="text/rest"/>')
   238             w(u'<input type="hidden" name="description_format" value="text/rest"/>')
   239             self.w(u'<input type="hidden" name="__bugreporting" value="1"/>')
   239             w(u'<input type="hidden" name="__bugreporting" value="1"/>')
   240             self.w(u'<input type="submit" value="%s"/>' % _('Submit bug report'))
   240             w(u'<input type="submit" value="%s"/>' % _('Submit bug report'))
   241             self.w(u'</fieldset>\n')
   241             w(u'</fieldset>\n')
   242             self.w(u'</form>\n')
   242             w(u'</form>\n')
   243         submitmail = self.config['submit-mail']
   243         submitmail = self.config['submit-mail']
   244         if submitmail:
   244         if submitmail:
   245             binfo = text_error_description(ex, excinfo, req, eversion,
   245             binfo = text_error_description(ex, excinfo, req, eversion,
   246                                            [(pkg, vcconf.get(pkg, _('no version information')))
   246                                            [(pkg, vcconf.get(pkg, _('no version information')))
   247                                             for pkg in self.config.cubes()])
   247                                             for pkg in self.config.cubes()])
   248             self.w(u'<form action="%s" method="post">\n' % req.build_url('reportbug'))
   248             w(u'<form action="%s" method="post">\n' % req.build_url('reportbug'))
   249             self.w(u'<fieldset>\n')
   249             w(u'<fieldset>\n')
   250             self.w(u'<input type="hidden" name="description" value="%s"/>' % html_escape(binfo))
   250             w(u'<input type="hidden" name="description" value="%s"/>' % html_escape(binfo))
   251             self.w(u'<input type="hidden" name="__bugreporting" value="1"/>')
   251             w(u'<input type="hidden" name="__bugreporting" value="1"/>')
   252             self.w(u'<input type="submit" value="%s"/>' % _('Submit bug report by mail'))
   252             w(u'<input type="submit" value="%s"/>' % _('Submit bug report by mail'))
   253             self.w(u'</fieldset>\n')
   253             w(u'</fieldset>\n')
   254             self.w(u'</form>\n')
   254             w(u'</form>\n')
   255 
   255 
   256 
   256 
   257 def exc_message(ex, encoding):
   257 def exc_message(ex, encoding):
   258     try:
   258     try:
   259         return unicode(ex)
   259         return unicode(ex)
   260     except:
   260     except:
   261         try:
   261         try:
   262             return unicode(str(ex), encoding, 'replace')
   262             return unicode(str(ex), encoding, 'replace')
   263         except:
   263         except:
   264             return unicode(repr(ex), encoding, 'replace')
   264             return unicode(repr(ex), encoding, 'replace')
   265     
   265 
   266 def text_error_description(ex, excinfo, req, eversion, cubes):
   266 def text_error_description(ex, excinfo, req, eversion, cubes):
   267     binfo = rest_traceback(excinfo, html_escape(ex))
   267     binfo = rest_traceback(excinfo, html_escape(ex))
   268     binfo += u'\n\n:URL: %s\n' % req.url()
   268     binfo += u'\n\n:URL: %s\n' % req.url()
   269     if not '__bugreporting' in req.form:
   269     if not '__bugreporting' in req.form:
   270         binfo += u'\n:form params:\n'
   270         binfo += u'\n:form params:\n'
   288     controller = 'edit'
   288     controller = 'edit'
   289     id = 'systemepropertiesform'
   289     id = 'systemepropertiesform'
   290     title = _('site configuration')
   290     title = _('site configuration')
   291     require_groups = ('managers',)
   291     require_groups = ('managers',)
   292     category = 'startupview'
   292     category = 'startupview'
   293     
   293 
   294     def linkable(self):
   294     def linkable(self):
   295         return True
   295         return True
   296     
   296 
   297     def url(self):
   297     def url(self):
   298         """return the url associated with this view. We can omit rql here"""
   298         """return the url associated with this view. We can omit rql here"""
   299         return self.build_url('view', vid=self.id)
   299         return self.build_url('view', vid=self.id)
   300     
   300 
   301     def call(self, **kwargs):
   301     def call(self, **kwargs):
   302         """The default view representing the application's index"""
   302         """The default view representing the application's index"""
   303         self.req.add_js('cubicweb.edition.js')
   303         self.req.add_js('cubicweb.edition.js')
   304         self.req.add_css('cubicweb.preferences.css')
   304         self.req.add_css('cubicweb.preferences.css')
   305         vreg = self.vreg
   305         vreg = self.vreg
   320         for group, keys in mainopts.items():
   320         for group, keys in mainopts.items():
   321             mainopts[group] = self.form(keys, False)
   321             mainopts[group] = self.form(keys, False)
   322         for group, objects in groupedopts.items():
   322         for group, objects in groupedopts.items():
   323             for oid, keys in objects.items():
   323             for oid, keys in objects.items():
   324                 groupedopts[group][oid] = self.form(keys, True)
   324                 groupedopts[group][oid] = self.form(keys, True)
   325         
   325 
   326         w = self.w
   326         w = self.w
   327         req = self.req
   327         req = self.req
   328         _ = req._
   328         _ = req._
   329         w(u'<h1>%s</h1>\n' % _(self.title))
   329         w(u'<h1>%s</h1>\n' % _(self.title))
   330         w(self.error_message())
   330         w(self.error_message())
   350                 if doc != docmsgid:
   350                 if doc != docmsgid:
   351                     w(u'<p class="description">%s</p>' % html_escape(doc))
   351                     w(u'<p class="description">%s</p>' % html_escape(doc))
   352                 w(form)
   352                 w(form)
   353                 w(u'</fieldset>')
   353                 w(u'</fieldset>')
   354             w(u'</div>')
   354             w(u'</div>')
   355             
   355 
   356                 
   356 
   357 
   357 
   358     @property
   358     @property
   359     @cached
   359     @cached
   360     def eprops_rset(self):
   360     def eprops_rset(self):
   361         return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V, NOT P for_user U')
   361         return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V, NOT P for_user U')
   362     
   362 
   363     @property
   363     @property
   364     def defined_keys(self):
   364     def defined_keys(self):
   365         values = {}
   365         values = {}
   366         for i, entity in enumerate(self.eprops_rset.entities()):
   366         for i, entity in enumerate(self.eprops_rset.entities()):
   367             values[entity.pkey] = i
   367             values[entity.pkey] = i
   368         return values
   368         return values
   369     
   369 
   370     def entity_for_key(self, key):
   370     def entity_for_key(self, key):
   371         values = self.defined_keys
   371         values = self.defined_keys
   372         if key in values:
   372         if key in values:
   373             entity = self.eprops_rset.get_entity(values[key], 0)
   373             entity = self.eprops_rset.get_entity(values[key], 0)
   374         else:
   374         else:
   389         if '?' in path:
   389         if '?' in path:
   390             path, params = path.split('?', 1)
   390             path, params = path.split('?', 1)
   391             w(u'<input type="hidden" name="__redirectparams" value="%s"/>\n'
   391             w(u'<input type="hidden" name="__redirectparams" value="%s"/>\n'
   392               % html_escape(params))
   392               % html_escape(params))
   393         w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % path)
   393         w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % path)
   394         #w(u'<input type="hidden" name="__redirectrql" value=""/>\n') 
   394         #w(u'<input type="hidden" name="__redirectrql" value=""/>\n')
   395         w(u'<input type="hidden" name="__message" value="%s"/>\n'
   395         w(u'<input type="hidden" name="__message" value="%s"/>\n'
   396           % self.req._('changes applied'))
   396           % self.req._('changes applied'))
   397         w(u'<table><tr><td>\n')
   397         w(u'<table><tr><td>\n')
   398        
   398 
   399         w(u'<table>\n')
   399         w(u'<table>\n')
   400         for key in keys:
   400         for key in keys:
   401             w(u'<tr>\n')
   401             w(u'<tr>\n')
   402             self.form_row(w, key, splitlabel)
   402             self.form_row(w, key, splitlabel)
   403             w(u'</tr>\n')
   403             w(u'</tr>\n')
   407         w(self.button_cancel())
   407         w(self.button_cancel())
   408         w(u'</td></tr></table>\n')
   408         w(u'</td></tr></table>\n')
   409         w(u'</fieldset>\n')
   409         w(u'</fieldset>\n')
   410         w(u'</form>\n')
   410         w(u'</form>\n')
   411         return stream.getvalue()
   411         return stream.getvalue()
   412         
   412 
   413     def form_row(self, w, key, splitlabel):
   413     def form_row(self, w, key, splitlabel):
   414         entity = self.entity_for_key(key)
   414         entity = self.entity_for_key(key)
   415         eid = entity.eid
   415         eid = entity.eid
   416         if splitlabel:
   416         if splitlabel:
   417             w(u'<td class="label">%s</td>' % self.req._(key.split('.')[-1]))
   417             w(u'<td class="label">%s</td>' % self.req._(key.split('.')[-1]))
   432         w(u'<input type="hidden" name="eid" value="%s"/>' % eid)
   432         w(u'<input type="hidden" name="eid" value="%s"/>' % eid)
   433         w(u'<input type="hidden" name="%s" value="EProperty"/>' % eid_param('__type', eid))
   433         w(u'<input type="hidden" name="%s" value="EProperty"/>' % eid_param('__type', eid))
   434         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('pkey', eid), key))
   434         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('pkey', eid), key))
   435         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('edits-pkey', eid), ''))
   435         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('edits-pkey', eid), ''))
   436 
   436 
   437         
   437 
   438 class EpropertiesForm(SystemEpropertiesForm):
   438 class EpropertiesForm(SystemEpropertiesForm):
   439     id = 'epropertiesform'
   439     id = 'epropertiesform'
   440     title = _('preferences')    
   440     title = _('preferences')
   441     require_groups = ('users', 'managers') # we don't want guests to be able to come here
   441     require_groups = ('users', 'managers') # we don't want guests to be able to come here
   442     __selectors__ = chainfirst(none_rset,
   442     __selectors__ = chainfirst(none_rset,
   443                                chainall(one_line_rset, accept_rset)),
   443                                chainall(one_line_rset, accept_rset)),
   444     accepts = ('EUser',)
   444     accepts = ('EUser',)
   445 
   445 
   447     def accept_rset(cls, req, rset, row, col):
   447     def accept_rset(cls, req, rset, row, col):
   448         if row is None:
   448         if row is None:
   449             row = 0
   449             row = 0
   450         score = super(EpropertiesForm, cls).accept_rset(req, rset, row, col)
   450         score = super(EpropertiesForm, cls).accept_rset(req, rset, row, col)
   451         # check current user is the rset user or he is in the managers group
   451         # check current user is the rset user or he is in the managers group
   452         if score and (req.user.eid == rset[row][col or 0] 
   452         if score and (req.user.eid == rset[row][col or 0]
   453                       or req.user.matching_groups('managers')):
   453                       or req.user.matching_groups('managers')):
   454             return score
   454             return score
   455         return 0
   455         return 0
   456 
   456 
   457     @property
   457     @property
   458     def user(self):
   458     def user(self):
   459         if self.rset is None:
   459         if self.rset is None:
   460             return self.req.user
   460             return self.req.user
   461         return self.rset.get_entity(self.row or 0, self.col or 0)
   461         return self.rset.get_entity(self.row or 0, self.col or 0)
   462     
   462 
   463     @property
   463     @property
   464     @cached
   464     @cached
   465     def eprops_rset(self):
   465     def eprops_rset(self):
   466         return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V,'
   466         return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V,'
   467                                 'P for_user U, U eid %(x)s', {'x': self.user.eid})
   467                                 'P for_user U, U eid %(x)s', {'x': self.user.eid})
   474             eid = entity.eid
   474             eid = entity.eid
   475             w(u'<input type="hidden" name="%s" value="%s"/>'
   475             w(u'<input type="hidden" name="%s" value="%s"/>'
   476               % (eid_param('edits-for_user', eid), INTERNAL_FIELD_VALUE))
   476               % (eid_param('edits-for_user', eid), INTERNAL_FIELD_VALUE))
   477             w(u'<input type="hidden" name="%s" value="%s"/>'
   477             w(u'<input type="hidden" name="%s" value="%s"/>'
   478               % (eid_param('for_user', eid), self.user.eid))
   478               % (eid_param('for_user', eid), self.user.eid))
   479     
   479 
   480                    
   480 
   481     
   481 
   482 
   482 
   483 class ProcessInformationView(StartupView):
   483 class ProcessInformationView(StartupView):
   484     id = 'info'
   484     id = 'info'
   485     title = _('server information')
   485     title = _('server information')
   486     require_groups = ('managers',)
   486     require_groups = ('managers',)