doc/book/annexes/faq.rst
changeset 10491 c67bcee93248
parent 10411 4ee15441f2eb
child 10496 e95b559a06a2
equal deleted inserted replaced
10490:76ab3c71aff2 10491:c67bcee93248
       
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 Frequently Asked Questions (FAQ)
       
     4 ================================
       
     5 
       
     6 
       
     7 Generalities
       
     8 ````````````
       
     9 
       
    10 Why do you use the LGPL license to prevent me from doing X ?
       
    11 ------------------------------------------------------------
       
    12 
       
    13 LGPL means that *if* you redistribute your application, you need to
       
    14 redistribute the changes you made to CubicWeb under the LGPL licence.
       
    15 
       
    16 Publishing a web site has nothing to do with redistributing source
       
    17 code according to the terms of the LGPL. A fair amount of companies
       
    18 use modified LGPL code for internal use. And someone could publish a
       
    19 *CubicWeb* component under a BSD licence for others to plug into a
       
    20 LGPL framework without any problem. The only thing we are trying to
       
    21 prevent here is someone taking the framework and packaging it as
       
    22 closed source to his own clients.
       
    23 
       
    24 Why does not CubicWeb have a template language ?
       
    25 ------------------------------------------------
       
    26 
       
    27 There are enough template languages out there. You can use your
       
    28 preferred template language if you want. [explain how to use a
       
    29 template language]
       
    30 
       
    31 *CubicWeb* does not define its own templating language as this was
       
    32 not our goal. Based on our experience, we realized that
       
    33 we could gain productivity by letting designers use design tools
       
    34 and developpers develop without the use of the templating language
       
    35 as an intermediary that could not be anyway efficient for both parties.
       
    36 Python is the templating language that we use in *CubicWeb*, but again,
       
    37 it does not prevent you from using a templating language.
       
    38 
       
    39 Moreover, CubicWeb currently supports `simpletal`_ out of the box and
       
    40 it is also possible to use the `cwtags`_ library to build html trees
       
    41 using the `with statement`_ with more comfort than raw strings.
       
    42 
       
    43 .. _`simpletal`: http://www.owlfish.com/software/simpleTAL/
       
    44 .. _`cwtags`: http://www.cubicweb.org/project/cwtags
       
    45 .. _`with statement`: http://www.python.org/dev/peps/pep-0343/
       
    46 
       
    47 Why do you think using pure python is better than using a template language ?
       
    48 -----------------------------------------------------------------------------
       
    49 
       
    50 Python is an Object Oriented Programming language and as such it
       
    51 already provides a consistent and strong architecture and syntax
       
    52 a templating language would not reach.
       
    53 
       
    54 Using Python instead of a template langage for describing the user interface
       
    55 makes it to maintain with real functions/classes/contexts without the need of
       
    56 learning a new dialect. By using Python, we use standard OOP techniques and
       
    57 this is a key factor in a robust application.
       
    58 
       
    59 CubicWeb looks pretty recent. Is it stable ?
       
    60 --------------------------------------------
       
    61 
       
    62 It is constantly evolving, piece by piece.  The framework has evolved since
       
    63 2001 and data has been migrated from one schema to the other ever since. There
       
    64 is a well-defined way to handle data and schema migration.
       
    65 
       
    66 You can see the roadmap there:
       
    67 http://www.cubicweb.org/project/cubicweb?tab=projectroadmap_tab.
       
    68 
       
    69 
       
    70 Why is the RQL query language looking similar to X ?
       
    71 ----------------------------------------------------
       
    72 
       
    73 It may remind you of SQL but it is higher level than SQL, more like
       
    74 SPARQL. Except that SPARQL did not exist when we started the project.
       
    75 With version 3.4, CubicWeb has support for SPARQL.
       
    76 
       
    77 The RQL language is what is going to make a difference with django-
       
    78 like frameworks for several reasons.
       
    79 
       
    80 1. accessing data is *much* easier with it. One can write complex
       
    81    queries with RQL that would be tedious to define and hard to maintain
       
    82    using an object/filter suite of method calls.
       
    83 
       
    84 2. it offers an abstraction layer allowing your applications to run
       
    85    on multiple back-ends. That means not only various SQL backends
       
    86    (postgresql, sqlite, sqlserver, mysql), but also non-SQL data stores like
       
    87    LDAP directories and subversion/mercurial repositories (see the `vcsfile`
       
    88    component).
       
    89 
       
    90 Which ajax library is CubicWeb using ?
       
    91 --------------------------------------
       
    92 
       
    93 CubicWeb uses jQuery_ and provides a few helpers on top of that. Additionally,
       
    94 some jQuery plugins are provided (some are provided in specific cubes).
       
    95 
       
    96 .. _jQuery: http://jquery.com
       
    97 
       
    98 
       
    99 Development
       
   100 ```````````
       
   101 
       
   102 How to change the instance logo ?
       
   103 ---------------------------------
       
   104 
       
   105 The logo is managed by css. You must provide a custom css that will contain
       
   106 the code below: 
       
   107 
       
   108 ::
       
   109    
       
   110      #logo {
       
   111         background-image: url("logo.jpg");
       
   112      }
       
   113 
       
   114 
       
   115 ``logo.jpg`` is in ``mycube/data`` directory.
       
   116 
       
   117 How to create an anonymous user ?
       
   118 ---------------------------------
       
   119 
       
   120 This allows to browse the site without being authenticated. In the
       
   121 ``all-in-one.conf`` file of your instance, define the anonymous user
       
   122 as follows ::
       
   123 
       
   124   # login of the CubicWeb user account to use for anonymous user (if you want to
       
   125   # allow anonymous)
       
   126   anonymous-user=anon
       
   127 
       
   128   # password of the CubicWeb user account matching login
       
   129   anonymous-password=anon
       
   130 
       
   131 You also must ensure that this `anon` user is a registered user of
       
   132 the DB backend. If not, you can create through the administation
       
   133 interface of your instance by adding a user with in the group `guests`.
       
   134 
       
   135 .. note::
       
   136     While creating a new instance, you can decide to allow access
       
   137     to anonymous user, which will automatically execute what is
       
   138     decribed above.
       
   139 
       
   140 How to load data from a python script ?
       
   141 ---------------------------------------
       
   142 Please, refer to :ref:`UsingPyro`.
       
   143 
       
   144 
       
   145 How to format an entity date attribute ?
       
   146 ----------------------------------------
       
   147 
       
   148 If your schema has an attribute of type `Date` or `Datetime`, you usually want to
       
   149 format it when displaying it. First, you should define your preferred format
       
   150 using the site configuration panel
       
   151 ``http://appurl/view?vid=systempropertiesform`` and then set ``ui.date`` and/or
       
   152 ``ui.datetime``.  Then in the view code, use:
       
   153 
       
   154 .. sourcecode:: python
       
   155 
       
   156     entity.printable_value(date_attribute)
       
   157 
       
   158 which will always return a string whatever the attribute's type (so it's
       
   159 recommended also for other attribute types). By default it expects to generate
       
   160 HTML, so it deals with rich text formating, xml escaping...
       
   161 
       
   162 How to update a database after a schema modification ?
       
   163 ------------------------------------------------------
       
   164 
       
   165 It depends on what has been modified in the schema.
       
   166 
       
   167 * update the permissions and properties of an entity or a relation:
       
   168   ``sync_schema_props_perms('MyEntityOrRelation')``.
       
   169 
       
   170 * add an attribute: ``add_attribute('MyEntityType', 'myattr')``.
       
   171 
       
   172 * add a relation: ``add_relation_definition('SubjRelation', 'MyRelation', 'ObjRelation')``.
       
   173 
       
   174 I get `NoSelectableObject` exceptions, how do I debug selectors ?
       
   175 -----------------------------------------------------------------
       
   176 
       
   177 You just need to put the appropriate context manager around view/component
       
   178 selection. One standard place for components is in cubicweb/vregistry.py: 
       
   179 
       
   180 .. sourcecode:: python
       
   181 
       
   182     def possible_objects(self, *args, **kwargs):
       
   183         """return an iterator on possible objects in this registry for the given
       
   184         context
       
   185         """
       
   186         from logilab.common.registry import traced_selection
       
   187         with traced_selection():
       
   188             for appobjects in self.itervalues():
       
   189                 try:
       
   190                     yield self._select_best(appobjects, *args, **kwargs)
       
   191                 except NoSelectableObject:
       
   192                     continue
       
   193 
       
   194 This will yield additional WARNINGs, like this::
       
   195 
       
   196     2009-01-09 16:43:52 - (cubicweb.selectors) WARNING: selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>
       
   197 
       
   198 For views, you can put this context in `cubicweb/web/views/basecontrollers.py` in
       
   199 the `ViewController`:
       
   200 
       
   201 .. sourcecode:: python
       
   202 
       
   203     def _select_view_and_rset(self, rset):
       
   204         ...
       
   205         try:
       
   206             from logilab.common.registry import traced_selection
       
   207             with traced_selection():
       
   208                 view = self._cw.vreg['views'].select(vid, req, rset=rset)
       
   209         except ObjectNotFound:
       
   210             self.warning("the view %s could not be found", vid)
       
   211             req.set_message(req._("The view %s could not be found") % vid)
       
   212             vid = vid_from_rset(req, rset, self._cw.vreg.schema)
       
   213             view = self._cw.vreg['views'].select(vid, req, rset=rset)
       
   214         ...
       
   215 
       
   216 I get "database is locked" when executing tests
       
   217 -----------------------------------------------
       
   218 
       
   219 If you have "database is locked" as error when you are executing security tests,
       
   220 it is usually because commit or rollback are missing before login() calls.
       
   221 
       
   222 You can also use a context manager, to avoid such errors, as described
       
   223 here: :ref:`securitytest`.
       
   224 
       
   225 
       
   226 What are hooks used for ?
       
   227 -------------------------
       
   228 
       
   229 Hooks are executed around (actually before or after) events.  The most common
       
   230 events are data creation, update and deletion.  They permit additional constraint
       
   231 checking (those not expressible at the schema level), pre and post computations
       
   232 depending on data movements.
       
   233 
       
   234 As such, they are a vital part of the framework.
       
   235 
       
   236 Other kinds of hooks, called Operations, are available
       
   237 for execution just before commit.
       
   238 
       
   239 For more information, read :ref:`hooks` section.
       
   240 
       
   241 
       
   242 Configuration
       
   243 `````````````
       
   244 
       
   245 How to configure a LDAP source ?
       
   246 --------------------------------
       
   247 
       
   248 See :ref:`LDAP`.
       
   249 
       
   250 How to import LDAP users in |cubicweb| ?
       
   251 ----------------------------------------
       
   252 
       
   253   Here is a useful script which enables you to import LDAP users
       
   254   into your *CubicWeb* instance by running the following:
       
   255 
       
   256 .. sourcecode:: python
       
   257 
       
   258     import os
       
   259     import pwd
       
   260     import sys
       
   261 
       
   262     from logilab.database import get_connection
       
   263 
       
   264     def getlogin():
       
   265         """avoid using os.getlogin() because of strange tty/stdin problems
       
   266         (man 3 getlogin)
       
   267         Another solution would be to use $LOGNAME, $USER or $USERNAME
       
   268         """
       
   269         return pwd.getpwuid(os.getuid())[0]
       
   270 
       
   271 
       
   272     try:
       
   273         database = sys.argv[1]
       
   274     except IndexError:
       
   275         print 'USAGE: python ldap2system.py <database>'
       
   276         sys.exit(1)
       
   277 
       
   278     if raw_input('update %s db ? [y/n]: ' % database).strip().lower().startswith('y'):
       
   279         cnx = get_connection(user=getlogin(), database=database)
       
   280         cursor = cnx.cursor()
       
   281 
       
   282         insert = ('INSERT INTO euser (creation_date, eid, modification_date, login, '
       
   283                   ' firstname, surname, last_login_time, upassword) '
       
   284                   "VALUES (%(mtime)s, %(eid)s, %(mtime)s, %(login)s, %(firstname)s, "
       
   285                   "%(surname)s, %(mtime)s, './fqEz5LeZnT6');")
       
   286         update = "UPDATE entities SET source='system' WHERE eid=%(eid)s;"
       
   287         cursor.execute("SELECT eid,type,source,extid,mtime FROM entities WHERE source!='system'")
       
   288         for eid, type, source, extid, mtime in cursor.fetchall():
       
   289             if type != 'CWUser':
       
   290                 print "don't know what to do with entity type", type
       
   291                 continue
       
   292             if source != 'ldapuser':
       
   293                 print "don't know what to do with source type", source
       
   294                 continue
       
   295             ldapinfos = dict(x.strip().split('=') for x in extid.split(','))
       
   296             login = ldapinfos['uid']
       
   297             firstname = ldapinfos['uid'][0].upper()
       
   298             surname = ldapinfos['uid'][1:].capitalize()
       
   299             if login != 'jcuissinat':
       
   300                 args = dict(eid=eid, type=type, source=source, login=login,
       
   301                             firstname=firstname, surname=surname, mtime=mtime)
       
   302                 print args
       
   303                 cursor.execute(insert, args)
       
   304                 cursor.execute(update, args)
       
   305 
       
   306         cnx.commit()
       
   307         cnx.close()
       
   308 
       
   309 
       
   310 Security
       
   311 ````````
       
   312 
       
   313 How to reset the password for user joe ?
       
   314 ----------------------------------------
       
   315 
       
   316 If you want to reset the admin password for ``myinstance``, do::
       
   317 
       
   318     $ cubicweb-ctl reset-admin-pwd myinstance
       
   319 
       
   320 You need to generate a new encrypted password::
       
   321 
       
   322     $ python
       
   323     >>> from cubicweb.server.utils import crypt_password
       
   324     >>> crypt_password('joepass')
       
   325     'qHO8282QN5Utg'
       
   326     >>>
       
   327 
       
   328 and paste it in the database::
       
   329 
       
   330     $ psql mydb
       
   331     mydb=> update cw_cwuser set cw_upassword='qHO8282QN5Utg' where cw_login='joe';
       
   332     UPDATE 1
       
   333 
       
   334 if you're running over SQL Server, you need to use the CONVERT
       
   335 function to convert the string to varbinary(255). The SQL query is
       
   336 therefore::
       
   337 
       
   338     update cw_cwuser set cw_upassword=CONVERT(varbinary(255), 'qHO8282QN5Utg') where cw_login='joe';
       
   339 
       
   340 Be careful, the encryption algorithm is different on Windows and on
       
   341 Unix. You cannot therefore use a hash generated on Unix to fill in a
       
   342 Windows database, nor the other way round.
       
   343 
       
   344 
       
   345 You can prefer use a migration script similar to this shell invocation instead::
       
   346 
       
   347     $ cubicweb-ctl shell <instance>
       
   348     >>> from cubicweb import Binary
       
   349     >>> from cubicweb.server.utils import crypt_password
       
   350     >>> crypted = crypt_password('joepass')
       
   351     >>> rset = rql('Any U WHERE U is CWUser, U login "joe"')
       
   352     >>> joe = rset.get_entity(0,0)
       
   353     >>> joe.cw_set(upassword=Binary(crypted))
       
   354 
       
   355 Please, refer to the script example is provided in the `misc/examples/chpasswd.py` file.
       
   356 
       
   357 The more experimented people would use RQL request directly::
       
   358 
       
   359     >>> rql('SET X upassword %(a)s WHERE X is CWUser, X login "joe"',
       
   360     ...     {'a': crypted})
       
   361 
       
   362 I've just created a user in a group and it doesn't work !
       
   363 ---------------------------------------------------------
       
   364 
       
   365 You are probably getting errors such as ::
       
   366 
       
   367   remove {'PR': 'Project', 'C': 'CWUser'} from solutions since your_user has no read access to cost
       
   368 
       
   369 This is because you have to put your user in the "users" group. The user has to
       
   370 be in both groups.
       
   371 
       
   372 How is security implemented ?
       
   373 ------------------------------
       
   374 
       
   375 The basis for security is a mapping from operations to groups or
       
   376 arbitrary RQL expressions. These mappings are scoped to entities and
       
   377 relations.
       
   378 
       
   379 This is an example for an Entity Type definition:
       
   380 
       
   381 .. sourcecode:: python
       
   382 
       
   383     class Version(EntityType):
       
   384         """a version is defining the content of a particular project's
       
   385         release"""
       
   386         # definition of attributes is voluntarily missing
       
   387         __permissions__ = {'read': ('managers', 'users', 'guests',),
       
   388                            'update': ('managers', 'logilab', 'owners'),
       
   389                            'delete': ('managers',),
       
   390                            'add': ('managers', 'logilab',
       
   391                                    ERQLExpression('X version_of PROJ, U in_group G, '
       
   392                                                   'PROJ require_permission P, '
       
   393                                                   'P name "add_version", P require_group G'),)}
       
   394 
       
   395 The above means that permission to read a Version is granted to any
       
   396 user that is part of one of the groups 'managers', 'users', 'guests'.
       
   397 The 'add' permission is granted to users in group 'managers' or
       
   398 'logilab' or to users in group G, if G is linked by a permission
       
   399 entity named "add_version" to the version's project.
       
   400 
       
   401 An example for a Relation Definition (RelationType both defines a
       
   402 relation type and implicitly one relation definition, on which the
       
   403 permissions actually apply):
       
   404 
       
   405 .. sourcecode:: python
       
   406 
       
   407     class version_of(RelationType):
       
   408         """link a version to its project. A version is necessarily linked
       
   409         to one and only one project. """
       
   410         # some lines voluntarily missing
       
   411         __permissions__ = {'read': ('managers', 'users', 'guests',),
       
   412                            'delete': ('managers', ),
       
   413                            'add': ('managers', 'logilab',
       
   414                                    RRQLExpression('O require_permission P, P name "add_version", '
       
   415                                                   'U in_group G, P require_group G'),) }
       
   416 
       
   417 The main difference lies in the basic available operations (there is
       
   418 no 'update' operation) and the usage of an RRQLExpression (rql
       
   419 expression for a relation) instead of an ERQLExpression (rql
       
   420 expression for an entity).
       
   421 
       
   422 You can find additional information in the section :ref:`securitymodel`.
       
   423 
       
   424 Is it possible to bypass security from the UI (web front) part ?
       
   425 ----------------------------------------------------------------
       
   426 
       
   427 No. Only Hooks/Operations can do that.
       
   428 
       
   429 Can PostgreSQL and CubicWeb authentication work with kerberos ?
       
   430 ----------------------------------------------------------------
       
   431 
       
   432 If you have PostgreSQL set up to accept kerberos authentication, you can set
       
   433 the db-host, db-name and db-user parameters in the `sources` configuration
       
   434 file while leaving the password blank. It should be enough for your
       
   435 instance to connect to postgresql with a kerberos ticket.
       
   436 
       
   437