1. 常见问题(FAQ)¶
1.1. 概述¶
1.1.1. 为什么使用LGPL许可证来阻止我执行X?¶
LGPL是指 if 您重新分配您的应用程序,您需要重新分配您在LGPL许可证下对CubicWeb所做的更改。
根据LGPL的条款,发布网站与重新发布源代码无关。相当多的公司使用修改后的LGPL代码进行内部使用。有人可以发布 CubicWeb BSD许可下的组件,其他人可以毫无问题地插入到LGPL框架中。我们在这里试图阻止的唯一一件事就是有人将框架作为封闭源代码打包到自己的客户机上。
1.1.2. 为什么CubicWeb没有模板语言?¶
有足够的模板语言。如果需要,可以使用首选的模板语言。 [解释如何使用模板语言]
CubicWeb 不定义自己的模板语言,因为这不是我们的目标。根据我们的经验,我们认识到,我们可以通过让设计师使用设计工具和开发人员开发而不使用模板语言作为中介来获得生产力,这对双方都是无效的。python是我们在 CubicWeb 但同样,它不会阻止您使用模板语言。
此外,CubicWeb目前支持 simpletal 开箱即用,也可以使用 cwtags 使用创建HTML树的库 with statement 比原始弦更舒适。
1.1.3. 为什么您认为使用纯Python比使用模板语言更好?¶
Python是一种面向对象的编程语言,因此它已经提供了一种模板语言无法达到的一致、强大的体系结构和语法。
使用python而不是模板语言来描述用户界面,使得它可以使用真实的函数/类/上下文进行维护,而无需学习新的方言。通过使用python,我们使用标准的OOP技术,这是健壮应用程序中的一个关键因素。
1.1.4. CubicWeb看起来很新。它稳定吗?¶
它不断地进化,一个一个地。该框架自2001年以来不断发展,数据从一个模式迁移到另一个模式。有一种定义良好的方法来处理数据和模式迁移。
你可以在那里看到路线图:http://www.cubicweb.org/project/cubicweb?tab=项目路线图_tab。
1.1.5. 为什么RQL查询语言看起来像X?¶
它可能会提醒您SQL,但它比SQL更高级,更像SPARQL。但在我们启动项目时,SPARQL不存在。在3.4版中,CubicWeb支持SPARQL。
RQL语言是将要与类似Django的框架产生差异的语言,原因有几个。
访问数据是 much 更简单。人们可以用rql编写复杂的查询,这将是一个冗长的定义,并且很难使用一组对象/过滤器方法调用来维护。
它提供了一个抽象层,允许应用程序在多个后端上运行。这不仅意味着各种SQL后端(postgresql、sqlite、sqlserver、mysql),还意味着非SQL数据存储,如LDAP目录和Subversion/Mercurial存储库(请参见 vcsfile 部件)。
1.1.6. CubicWeb使用哪个Ajax库?¶
CubicWeb使用 jQuery 除此之外,还提供了一些帮助。此外,还提供了一些jquery插件(一些插件在特定的多维数据集中提供)。
1.2. 开发¶
1.2.1. 如何更改实例徽标?¶
徽标由CSS管理。必须提供包含以下代码的自定义CSS:
#logo {
background-image: url("logo.jpg");
}
logo.jpg
是在 mycube/data
目录。
1.2.2. 如何创建匿名用户?¶
这允许在未经身份验证的情况下浏览网站。在 all-in-one.conf
实例的文件,按如下方式定义匿名用户:
# login of the CubicWeb user account to use for anonymous user (if you want to
# allow anonymous)
anonymous-user=anon
# password of the CubicWeb user account matching login
anonymous-password=anon
您还必须确保 anon 用户是数据库后端的注册用户。如果没有,则可以通过实例的管理界面创建,方法是在组中添加一个 guests .
注解
创建新实例时,您可以决定允许匿名用户访问,匿名用户将自动执行上面描述的操作。
1.2.3. 如何设置实体日期属性的格式?¶
如果架构具有类型的属性 Date 或 Datetime ,您通常希望在显示时格式化它。首先,您应该使用站点配置面板定义首选格式。 http://appurl/view?vid=systempropertiesform
然后设置 ui.date
和/或 ui.datetime
.然后在视图代码中,使用:
entity.printable_value(date_attribute)
它将始终返回一个字符串,不管属性的类型是什么(因此建议对其他属性类型也使用)。默认情况下,它期望生成HTML,因此它处理富文本格式、XML转义…
1.2.4. 模式修改后如何更新数据库?¶
这取决于模式中修改了什么。
更新实体或关系的权限和属性:
sync_schema_props_perms('MyEntityOrRelation')
.添加属性:
add_attribute('MyEntityType', 'myattr')
.添加关系:
add_relation_definition('SubjRelation', 'MyRelation', 'ObjRelation')
.
1.2.5. 我明白了 NoSelectableObject 异常,如何调试选择器?¶
您只需要在视图/组件选择周围放置适当的上下文管理器。组件的一个标准位置在cubicWeb/vregistry.py中:
def possible_objects(self, *args, **kwargs):
"""return an iterator on possible objects in this registry for the given
context
"""
from logilab.common.registry import traced_selection
with traced_selection():
for appobjects in self.itervalues():
try:
yield self._select_best(appobjects, *args, **kwargs)
except NoSelectableObject:
continue
这将产生额外的警告,如:
2009-01-09 16:43:52 - (cubicweb.selectors) WARNING: selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>
对于视图,可以将此上下文放入 cubicweb/web/views/basecontrollers.py 在 ViewController :
def _select_view_and_rset(self, rset):
...
try:
from logilab.common.registry import traced_selection
with traced_selection():
view = self._cw.vreg['views'].select(vid, req, rset=rset)
except ObjectNotFound:
self.warning("the view %s could not be found", vid)
req.set_message(req._("The view %s could not be found") % vid)
vid = vid_from_rset(req, rset, self._cw.vreg.schema)
view = self._cw.vreg['views'].select(vid, req, rset=rset)
...
1.2.6. 我在执行测试时得到“数据库被锁定”¶
如果在执行安全测试时“数据库被锁定”为错误,通常是因为在login()调用之前缺少commit或rollback。
您还可以使用上下文管理器来避免此类错误,如下所述: 管理连接或用户 .
1.2.7. 钩子是用来做什么的?¶
钩子在事件前后执行。最常见的事件是数据创建、更新和删除。它们允许额外的约束检查(那些在模式级别不可表示的约束检查)、根据数据移动进行计算前和计算后的检查。
因此,它们是框架的重要组成部分。
其他类型的钩子(称为操作)可在提交之前执行。
有关详细信息,请阅读 挂钩和操作 部分。
1.3. 配置¶
1.3.1. 如何配置LDAP源?¶
见 LDAP集成 .
1.3.2. 如何导入LDAP用户 CubicWeb 是吗?¶
下面是一个有用的脚本,它使您能够将LDAP用户导入到 CubicWeb 通过运行以下命令执行实例:
import os
import pwd
import sys
from logilab.database import get_connection
def getlogin():
"""avoid using os.getlogin() because of strange tty/stdin problems
(man 3 getlogin)
Another solution would be to use $LOGNAME, $USER or $USERNAME
"""
return pwd.getpwuid(os.getuid())[0]
try:
database = sys.argv[1]
except IndexError:
print 'USAGE: python ldap2system.py <database>'
sys.exit(1)
if raw_input('update %s db ? [y/n]: ' % database).strip().lower().startswith('y'):
cnx = get_connection(user=getlogin(), database=database)
cursor = cnx.cursor()
insert = ('INSERT INTO euser (creation_date, eid, modification_date, login, '
' firstname, surname, last_login_time, upassword) '
"VALUES (%(mtime)s, %(eid)s, %(mtime)s, %(login)s, %(firstname)s, "
"%(surname)s, %(mtime)s, './fqEz5LeZnT6');")
update = "UPDATE entities SET source='system' WHERE eid=%(eid)s;"
cursor.execute("SELECT eid,type,source,extid,mtime FROM entities WHERE source!='system'")
for eid, type, source, extid, mtime in cursor.fetchall():
if type != 'CWUser':
print "don't know what to do with entity type", type
continue
if source != 'ldapuser':
print "don't know what to do with source type", source
continue
ldapinfos = dict(x.strip().split('=') for x in extid.split(','))
login = ldapinfos['uid']
firstname = ldapinfos['uid'][0].upper()
surname = ldapinfos['uid'][1:].capitalize()
if login != 'jcuissinat':
args = dict(eid=eid, type=type, source=source, login=login,
firstname=firstname, surname=surname, mtime=mtime)
print args
cursor.execute(insert, args)
cursor.execute(update, args)
cnx.commit()
cnx.close()
1.4. 安全性¶
1.4.1. 如何重置用户joe的密码?¶
如果要重置的管理员密码 myinstance
DO::
$ cubicweb-ctl reset-admin-pwd myinstance
您需要生成新的加密密码::
$ python
>>> from cubicweb.server.utils import crypt_password
>>> crypt_password('joepass')
'qHO8282QN5Utg'
>>>
并将其粘贴到数据库中:
$ psql mydb
mydb=> update cw_cwuser set cw_upassword='qHO8282QN5Utg' where cw_login='joe';
UPDATE 1
如果运行的是SQL Server,则需要使用convert函数将字符串转换为varbinary(255)。因此,SQL查询是:
update cw_cwuser set cw_upassword=CONVERT(varbinary(255), 'qHO8282QN5Utg') where cw_login='joe';
注意,Windows和Unix上的加密算法不同。因此,不能使用在Unix上生成的哈希来填充Windows数据库,也不能反过来使用。
您可以使用类似于此shell调用的迁移脚本,而不是:
$ cubicweb-ctl shell <instance>
>>> from cubicweb import Binary
>>> from cubicweb.server.utils import crypt_password
>>> crypted = crypt_password('joepass')
>>> rset = rql('Any U WHERE U is CWUser, U login "joe"')
>>> joe = rset.get_entity(0,0)
>>> joe.cw_set(upassword=Binary(crypted))
请参阅中提供的脚本示例 misc/examples/chpasswd.py 文件。
更多的实验人员将直接使用RQL请求:
>>> rql('SET X upassword %(a)s WHERE X is CWUser, X login "joe"',
... {'a': crypted})
1.4.2. 我刚在一个组中创建了一个用户,但它不起作用!¶
您可能会遇到以下错误:
remove {'PR': 'Project', 'C': 'CWUser'} from solutions since your_user has no read access to cost
这是因为您必须将用户放在“用户”组中。用户必须同时在两个组中。
1.4.3. 安全如何实施?¶
安全性的基础是从操作到组或任意RQL表达式的映射。这些映射的作用域是实体和关系。
这是实体类型定义的示例:
class Version(EntityType):
"""a version is defining the content of a particular project's
release"""
# definition of attributes is voluntarily missing
__permissions__ = {'read': ('managers', 'users', 'guests',),
'update': ('managers', 'logilab', 'owners'),
'delete': ('managers',),
'add': ('managers', 'logilab',
ERQLExpression('X version_of PROJ, U in_group G, '
'PROJ require_permission P, '
'P name "add_version", P require_group G'),)}
上面的意思是,读取版本的权限授予属于“经理”、“用户”、“来宾”组之一的任何用户。如果G由名为“添加版本”的权限实体链接到版本的项目,则“添加”权限将授予组“经理”或“逻辑实验室”中的用户或组G中的用户。
关系定义的示例(relation type既定义了关系类型,又隐式地定义了一个关系定义,在该定义上实际应用了权限):
class version_of(RelationType):
"""link a version to its project. A version is necessarily linked
to one and only one project. """
# some lines voluntarily missing
__permissions__ = {'read': ('managers', 'users', 'guests',),
'delete': ('managers', ),
'add': ('managers', 'logilab',
RRQLExpression('O require_permission P, P name "add_version", '
'U in_group G, P require_group G'),) }
主要区别在于基本的可用操作(没有“更新”操作)和使用rrqlExpression(关系的rql表达式)而不是erqlExpression(实体的rql表达式)。
您可以在部分中找到其他信息 安全模式 .
1.4.4. 是否可以绕过UI(Web前端)部分的安全性?¶
不,只有钩子/操作可以做到这一点。
1.4.5. PostgreSQL和CubicWeb身份验证能否与Kerberos一起工作?¶
如果PostgreSQL设置为接受Kerberos身份验证,则可以在 sources 将密码留空时的配置文件。对于您的实例来说,使用一个Kerberos票据连接到PostgreSQL应该已经足够了。