cubicweb/web/views/management.py
changeset 11057 0b59724cb3f2
parent 10922 7d01c8c675a0
child 11732 45c38bd3e96d
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
       
     1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     3 #
       
     4 # This file is part of CubicWeb.
       
     5 #
       
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     7 # terms of the GNU Lesser General Public License as published by the Free
       
     8 # Software Foundation, either version 2.1 of the License, or (at your option)
       
     9 # any later version.
       
    10 #
       
    11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    14 # details.
       
    15 #
       
    16 # You should have received a copy of the GNU Lesser General Public License along
       
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    18 """security management and error screens"""
       
    19 
       
    20 __docformat__ = "restructuredtext en"
       
    21 from cubicweb import _
       
    22 
       
    23 
       
    24 from logilab.mtconverter import xml_escape
       
    25 from logilab.common.registry import yes
       
    26 
       
    27 from cubicweb.predicates import none_rset, match_user_groups, authenticated_user
       
    28 from cubicweb.view import AnyRsetView, StartupView, EntityView, View
       
    29 from cubicweb.uilib import html_traceback, rest_traceback, exc_message
       
    30 from cubicweb.web import formwidgets as wdgs
       
    31 from cubicweb.web.formfields import guess_field
       
    32 from cubicweb.web.views.schema import SecurityViewMixIn
       
    33 
       
    34 from yams.buildobjs import EntityType
       
    35 
       
    36 SUBMIT_MSGID = _('Submit bug report')
       
    37 MAIL_SUBMIT_MSGID = _('Submit bug report by mail')
       
    38 
       
    39 class SecurityManagementView(SecurityViewMixIn, EntityView):
       
    40     """display security information for a given entity"""
       
    41     __regid__ = 'security'
       
    42     __select__ = EntityView.__select__ & authenticated_user()
       
    43 
       
    44     title = _('security')
       
    45 
       
    46     def call(self):
       
    47         self.w(u'<div id="progress">%s</div>' % self._cw._('validating...'))
       
    48         super(SecurityManagementView, self).call()
       
    49 
       
    50     def entity_call(self, entity):
       
    51         self._cw.add_js('cubicweb.edition.js')
       
    52         self._cw.add_css('cubicweb.acl.css')
       
    53         w = self.w
       
    54         _ = self._cw._
       
    55         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
       
    56           % (entity.dc_type().capitalize(),
       
    57              xml_escape(entity.absolute_url()),
       
    58              xml_escape(entity.dc_title())))
       
    59         # first show permissions defined by the schema
       
    60         self.w('<h2>%s</h2>' % _('Schema\'s permissions definitions'))
       
    61         self.permissions_table(entity.e_schema)
       
    62         self.w('<h2>%s</h2>' % _('Manage security'))
       
    63         # ownership information
       
    64         if self._cw.vreg.schema.rschema('owned_by').has_perm(self._cw, 'add',
       
    65                                                     fromeid=entity.eid):
       
    66             self.owned_by_edit_form(entity)
       
    67         else:
       
    68             self.owned_by_information(entity)
       
    69 
       
    70     def owned_by_edit_form(self, entity):
       
    71         self.w('<h3>%s</h3>' % self._cw._('Ownership'))
       
    72         msg = self._cw._('ownerships have been changed')
       
    73         form = self._cw.vreg['forms'].select('base', self._cw, entity=entity,
       
    74                                          form_renderer_id='onerowtable', submitmsg=msg,
       
    75                                          form_buttons=[wdgs.SubmitButton()],
       
    76                                          domid='ownership%s' % entity.eid,
       
    77                                          __redirectvid='security',
       
    78                                          __redirectpath=entity.rest_path())
       
    79         field = guess_field(entity.e_schema,
       
    80                             self._cw.vreg.schema['owned_by'],
       
    81                             req=self._cw)
       
    82         form.append_field(field)
       
    83         form.render(w=self.w, display_progress_div=False)
       
    84 
       
    85     def owned_by_information(self, entity):
       
    86         ownersrset = entity.related('owned_by')
       
    87         if ownersrset:
       
    88             self.w('<h3>%s</h3>' % self._cw._('Ownership'))
       
    89             self.w(u'<div class="ownerInfo">')
       
    90             self.w(self._cw._('this entity is currently owned by') + ' ')
       
    91             self.wview('csv', entity.related('owned_by'), 'null')
       
    92             self.w(u'</div>')
       
    93         # else we don't know if this is because entity has no owner or becayse
       
    94         # user as no access to owner users entities
       
    95 
       
    96 
       
    97 class ErrorView(AnyRsetView):
       
    98     """default view when no result has been found"""
       
    99     __select__ = yes()
       
   100     __regid__ = 'error'
       
   101 
       
   102     def page_title(self):
       
   103         """returns a title according to the result set - used for the
       
   104         title in the HTML header
       
   105         """
       
   106         return self._cw._('an error occurred')
       
   107 
       
   108     def _excinfo(self):
       
   109         req = self._cw
       
   110         ex = req.data.get('ex')
       
   111         excinfo = req.data.get('excinfo')
       
   112         if 'errmsg' in req.data:
       
   113             errmsg = req.data['errmsg']
       
   114             exclass = None
       
   115         else:
       
   116             errmsg = exc_message(ex, req.encoding)
       
   117             exclass = ex.__class__.__name__
       
   118         return errmsg, exclass, excinfo
       
   119 
       
   120     def call(self):
       
   121         req = self._cw.reset_headers()
       
   122         w = self.w
       
   123         title = self._cw._('an error occurred')
       
   124         w(u'<h2>%s</h2>' % title)
       
   125         ex, exclass, excinfo = self._excinfo()
       
   126         if excinfo is not None and self._cw.vreg.config['print-traceback']:
       
   127             if exclass is None:
       
   128                 w(u'<div class="tb">%s</div>'
       
   129                        % xml_escape(ex).replace("\n","<br />"))
       
   130             else:
       
   131                 w(u'<div class="tb">%s: %s</div>'
       
   132                        % (exclass, xml_escape(ex).replace("\n","<br />")))
       
   133             w(u'<hr />')
       
   134             w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
       
   135         else:
       
   136             w(u'<div class="tb">%s</div>' % (xml_escape(ex).replace("\n","<br />")))
       
   137         # if excinfo is not None, it's probably not a bug
       
   138         if excinfo is None:
       
   139             return
       
   140         vcconf = self._cw.cnx.repo.get_versions()
       
   141         w(u"<div>")
       
   142         eversion = vcconf.get('cubicweb', self._cw._('no version information'))
       
   143         # NOTE: tuple wrapping needed since eversion is itself a tuple
       
   144         w(u"<b>CubicWeb version:</b> %s<br/>\n" % (eversion,))
       
   145         cversions = []
       
   146         for cube in self._cw.vreg.config.cubes():
       
   147             cubeversion = vcconf.get(cube, self._cw._('no version information'))
       
   148             w(u"<b>Cube %s version:</b> %s<br/>\n" % (cube, cubeversion))
       
   149             cversions.append((cube, cubeversion))
       
   150         w(u"</div>")
       
   151         # creates a bug submission link if submit-mail is set
       
   152         if self._cw.vreg.config['submit-mail']:
       
   153             form = self._cw.vreg['forms'].select('base', self._cw, rset=None,
       
   154                                                  mainform=False)
       
   155             binfo = text_error_description(ex, excinfo, req, eversion, cversions)
       
   156             form.add_hidden('description', binfo,
       
   157                             # we must use a text area to keep line breaks
       
   158                             widget=wdgs.TextArea({'class': 'hidden'}))
       
   159             # add a signature so one can't send arbitrary text
       
   160             form.add_hidden('__signature', req.vreg.config.sign_text(binfo))
       
   161             form.add_hidden('__bugreporting', '1')
       
   162             form.form_buttons = [wdgs.SubmitButton(MAIL_SUBMIT_MSGID)]
       
   163             form.action = req.build_url('reportbug')
       
   164             form.render(w=w)
       
   165 
       
   166 
       
   167 def text_error_description(ex, excinfo, req, eversion, cubes):
       
   168     binfo = rest_traceback(excinfo, xml_escape(ex))
       
   169     binfo += u'\n\n:URL: %s\n' % req.url()
       
   170     if not '__bugreporting' in req.form:
       
   171         binfo += u'\n:form params:\n'
       
   172         binfo += u'\n'.join(u'  * %s = %s' % (k, v) for k, v in req.form.items())
       
   173     binfo += u'\n\n:CubicWeb version: %s\n'  % (eversion,)
       
   174     for pkg, pkgversion in cubes:
       
   175         binfo += u":Cube %s version: %s\n" % (pkg, pkgversion)
       
   176     binfo += '\n'
       
   177     return binfo
       
   178 
       
   179 
       
   180 class CwStats(View):
       
   181     """A textual stats output for monitoring tools such as munin """
       
   182 
       
   183     __regid__ = 'processinfo'
       
   184     content_type = 'text/plain'
       
   185     templatable = False
       
   186     __select__ = none_rset() & match_user_groups('users', 'managers')
       
   187 
       
   188     def call(self):
       
   189         stats = self._cw.call_service('repo_stats')
       
   190         stats['looping_tasks'] = ', '.join('%s (%s seconds)' % (n, i) for n, i in stats['looping_tasks'])
       
   191         stats['threads'] = ', '.join(sorted(stats['threads']))
       
   192         for k in stats:
       
   193             if k in ('extid_cache_size', 'type_source_cache_size'):
       
   194                 continue
       
   195             if k.endswith('_cache_size'):
       
   196                 stats[k] = '%s / %s' % (stats[k]['size'], stats[k]['maxsize'])
       
   197         results = []
       
   198         for element in stats:
       
   199             results.append(u'%s %s' % (element, stats[element]))
       
   200         self.w(u'\n'.join(results))