martes, 12 de agosto de 2008

Bloquear perfiles según patrón

0 comentarios
 

El funcionamiento por defecto de la seguridad en proyectos de KMKey consiste en tener al menos los siguientes perfiles a nivel de aplicación:

  • WorkspaceReader: asignado a todo el mundo con usuario (Authenticated)
  • WorkspaceMember: asignado a aquellos usuarios con capacidad de creación de proyectos o contactos
  • WorkspaceManager: asignado únicamente al administrador

Por defecto, al crear un nuevo proyecto, se bloquean los roles WorkspaceReader y WorkspaceMember, de forma que sólo WorkspaceManager + los usuarios asignados localmente al proyecto tienen acceso al mismo.

Como este esquema de perfiles de aplicación se amplía con frecuencia, existía en KMKey una propiedad del portal que permitía definir qué perfiles deben bloquearse cada vez que se cree un proyecto. El problema se daba cuando ciertos usuarios debían ver todos los proyectos de un tipo, pero no todos los de otro tipo. Para solucionar este caso, se ha trasladado al patrón de trabajo la configuración de qué perfiles deben ser bloqueados cada vez que se cree un proyecto basado en ese patrón, dando así respuesta a todos los casos planteados.

Leer más...
viernes, 11 de julio de 2008

Incluir links a objetos en un patrón de trabajo

0 comentarios
 

Desde la versión 08.07.01 KMKey incorpora la posibilidad de incluir en la definición de los patrones de trabajo enlaces a otros objetos existentes. Ello se traduce en que cada vez que se crea un proyecto basado en ese patrón de trabajo, se crean también enlaces a esos objetos.


El caso concreto que fomentó este desarrollo era el de un cliente que tenía toda una serie de documentación de referencia y quería que dicha documentación fuera incluida automáticamente en ciertas tareas de cada proyecto, pero en forma de enlace, es decir, que en los proyectos no hubiera un duplicado del documento, sinó un apunte al documento original.

Para configurar esta funcionalidad, basta con incluir las sentencias correspondientes en el XML de creación de objetos del patrón de trabajo:




<default_portal_type tag="proxy"
portal_type="CPS Proxy Document" /> 


<task task_id="2" Title="2 Cables"
responsible="role:comercial"
planned_start="root['planned_start']+0"
planned_end="parent['planned_end']+0">
  <proxy
id="prova" docid="2094376454"
default_language="es" language_revs="{'es':1}"
/>
</task>







Como se observa, la sentencia proxy debe incluir el id del nuevo objeto (puede ser cualquiera mientres no colisione), el docid del objecto orígen, el idioma (siempre "es"), y la revisión a la que se apunta (puede ser 1, 2, 3 ... en función de la versión del documento original a la que se quiera apuntar

Leer más...
viernes, 20 de junio de 2008

Bloquear partes de un upgrade

1 comentarios
 

De vez en cuando es necesario configurar de forma distinta, para un cliente en concreto, partes genéricas de la aplicación. Por ejemplo, en clientes donde no se use la gestión de recursos, puede ser necesario deshabilitar el action correspondiente en el portal_actions. Pero ese cambio desaparecería al realizarse el próximo import del step "Actions Provideers". Para evitarlo se ha incluido, en la versión 08.06.01, un nuevo atributo "block_import", que permite marcar qué acciones deseamos que se importen de nuevo y cuales deseamos mantener sin cambios.


El mismo concepto se ha aplicado a los portal_layouts. Cuando queremos bloquear las actualizaciones de un layout concret, podemos añadir al mismo una Property "block_import", de tipo Boolean, con valor True

Leer más...
lunes, 16 de junio de 2008

Gestionar Traducciones en KMKey

0 comentarios
 

KMKey está desarrollado sobre CPS y Zope 2.9.4, con lo que gestiona las traducciones por dos vías distintas: la incorporada por CPS, usando Localizer al estilo Zope 2, y la incorporada por Five al estilo Zope 3. Es importante tener claro qué partes del programa usan cada uno de los tipos de traducción:

  1. En general, todo lo que forma parte del código python o TAL se traduce con el sistema de Zope 3, mediante un extractor capaz de localizar las cadenas e incorporarlas en el directorio Producto/locales/idioma/LC_MESSAGES.

  2. Las cadenas propias de la configuración via ZMI, como nombres de TABs o Actions, de menús, de campos, etc, se traducen mediante el antiguo sistema de Zope 2. En este caso se carece de extractor, y las cadenas deben ir introduciéndose manualmente en el i18n/default.pot

Para extraer las cadenas a traducir necesitaremos una instancia de Zope 3, perferentemente superior o igual a 3.4.0. Por ejemplo:

wget http://www.zope.org/Products/Zope3/3.4.0c1/Zope-3.4.0c1.tgz

tar xzf Zope-3.4.0c1.tgz

cd Zope-3.4.0c1

./configure –prefix=/usr/local/zope340c1

make

make install

/usr/local/zope340c1/bin/mkzopeinstance -d /usr/local/z3instance

Ahora ya podemos realizar la extracción de cadenas de KMKey y traducirlas. Por ejemplo:

cd Products/KMKeyDefault

/usr/local/z3instance/bin/i18nextract -p . -o locales -d kmkeydefault

/usr/local/z3instance/bin/i18nmergeall -l locales

cd locales/es/LC_MESSAGES/

poedit kmkeydefault.po

Para ver en funcionamiento las nuevas traducciones, recordemos siempre que debemos regenerar los ficheros .mo:

python2.4 ../KMKeyCore/utils/generate_mo_files.py

Para incluir traducciones de Zope 2, deberemos editar manualmente el i18n/default.pot, y añadir las nuevas entradas, sin traducción. Después debemos mezclar con cada uno de los idiomas y traducir.

msgmerge -o es.po -s es.po default.pot

poedit es.po

Para que este tipo de traducciones sean visibles desde la aplicación, es necesario realizar el import del step Localizer desde el ZMI portal_setup. pestaña imports

Leer más...
lunes, 4 de febrero de 2008

Expresiones de fórmulas en KMKey

0 comentarios
 
Cuando configuramos uszndo el ZMI (para usuarios avanzados), hay un montón de sitios donde podemos definir fórmulas usando expresiones TALES. En cada caso, los objetos disponibles pueden ser diferentes, y es dificil recordarlos. Aquí dejo una lista de los más usados:

Expressions used in Default Value of Fields

mapping = {
'field': self,
'datamodel': datamodel,
'user': getSecurityManager().getUser(),
'portal': getToolByName(self, 'portal_url').getPortalObject(),
'modules': SecureModuleImporter,
'DateTime': DateTime,
'nothing': None,
}


Expressions used in Fields

mapping = data.copy() # XXX there may be DEFAULT_VALUE_MARKER here

# XXX hack replace DEFAULT_VALUE_MARKER
for k, v in mapping.items():
if v is DEFAULT_VALUE_MARKER:
mapping[k] = '' # XXX should be field's default
portal = getToolByName(self, "portal_url").getPortalObject()

# Wrapping util in the current acquisition context
util = fieldStorageNamespace.__of__(portal)

mapping.update({
'value': value,
'data': data,
'field': self,
'user': getSecurityManager().getUser(),
'portal': portal,
'modules': SecureModuleImporter,
'DateTime': DateTime,
'nothing': None,
# Useful for objects
'object': context,
'proxy': proxy,
# Deprecated: use the 'object' name instead
'context': context,
# Methods registry
'util': util,
})


Expressions used in Layouts

portal = getToolByName(self, 'portal_url').getPortalObject()
data = {
'layout': self,
'datastructure': datastructure,
'datamodel' : datastructure.getDataModel(),
'kw': kw,
'nothing': None,
'portal': portal,
'modules': SecureModuleImporter,
}


Expressions used in Widgets

wftool = getToolByName(self, 'portal_workflow')
portal = getToolByName(self, 'portal_url').getPortalObject()
proxy = datamodel._proxy
if proxy is not None:
review_state = wftool.getInfoFor(proxy, 'review_state', None)
else:
review_state = None
data = {
'widget': self,
'datamodel': datamodel,
'user': datamodel._acl_cache_user,
'nothing': None,
'context': datamodel._context,
'portal': portal,
'modules': SecureModuleImporter,
'proxy': proxy,
'portal_workflow': wftool,
'review_state': review_state,
'layout_mode': layout_mode,
}

Expressions used in Workflows

ob = sci.object
wf = sci.workflow
data = {
'here': ob,
'container': aq_parent(aq_inner(ob)),
'nothing': None,
'root': wf.getPhysicalRoot(),
'request': getattr( ob, 'REQUEST', None ),
'modules': SecureModuleImporter,
'user': getSecurityManager().getUser(),
'state_change': sci,
'transition': sci.transition,
'status': sci.status,
'stacks': sci.stacks,
'kwargs': sci.kwargs,
'workflow': wf,
'scripts': wf.scripts,
}


Expressions used in Actions

data = {
'object_url': object_url,
'folder_url': folder.absolute_url(),
'portal_url': portal.absolute_url(),
'object': object,
'folder': folder,
'portal': portal,
'nothing': None,
'request': getattr( object, 'REQUEST', None ),
'modules': SecureModuleImporter,
'member': member,
'here': object,
}


Expressions used in KMKey Relation Widgets conditions

query = catalog.makeAdvancedQuery({})
if self.query_expression:
data = {
'widget': self,
'datastructure': datastructure,
'datamodel' : datastructure.getDataModel(),
'kw': kw,
'nothing': None,
'modules': SecureModuleImporter,
'MatchGlob': MatchGlob,
'Eq': Eq,
'Le': Le,
'Ge': Ge,
'In': In,
'Between': Between,
'Generic': Generic
}
Leer más...