Monday, January 23, 2012

Adding test users programmatically using collective.recipe.plonesite

I'm writing some functional tests for a Plone project and I need to add a group of test users every time I create a test site.

collective.recipe.plonesite is a cool Buildout recipe that enables you to create and update a Plone site as part of a buildout run.

I added the following lines to my buildout configuration:

parts =
    …
    plonesite

[plonesite]
recipe = collective.recipe.plonesite
profiles = my.project:default
post-extras = ${buildout:directory}/acceptance-tests/add_test_users.py

The code of the add_test_users.py script is pretty straightforward:

"""This script will add a number of test users to a Plone site.

You can used it in post-extras option of collective.recipe.plonesite. It will
be evaluated after running QuickInstaller and GenericSetup profiles.

@param portal: The Plone site as defined by the site-id option
"""

import logging
logger = logging.getLogger('collective.recipe.plonesite')

test_users = [
    # (username, password, group),
    ('username1', 'password1', 'group1'),
    ('username2', 'password2', 'group2'),
    ('username3', 'password3', 'group3'),
    ]

for username, password, group in test_users:
    if username not in portal.acl_users.getUserIds():
        try:
            portal.portal_registration.addMember(username, password)
            portal.portal_groups.addPrincipalToGroup(username, group)
        except ValueError:
            logger.warn('The login name "%s" is not valid.' % username)
        except KeyError:
            logger.warn('The group "%s" is not valid.' % group)

Enjoy!

(Next time I'll give you my first impressions on SeleniumLibrary, a web testing library for Robot Framework, I'm using to write the tests.)

Friday, January 13, 2012

Setting the right permissions on your blobstorage directory

Have you ever been annoyed by a message saying that the blobstorage directory of your instance has an insecure mode setting?

That happens to me all the time, so today I spent a couple of minutes trying to figure out how to fix it.

In ZODB/blob.py we have the following:

class FilesystemHelper:
    # Storages that implement IBlobStorage can choose to use this
    # helper class to generate and parse blob filenames.  This is not
    # a set-in-stone interface for all filesystem operations dealing
    # with blobs and storages needn't indirect through this if they
    # want to perform blob storage differently.

    …

    def create(self):
        if not os.path.exists(self.base_dir):
            os.makedirs(self.base_dir, 0700)
            log("Blob directory '%s' does not exist. "
                "Created new directory." % self.base_dir)
        if not os.path.exists(self.temp_dir):
            os.makedirs(self.temp_dir, 0700)
            log("Blob temporary directory '%s' does not exist. "
                "Created new directory." % self.temp_dir)

        if not os.path.exists(os.path.join(self.base_dir, LAYOUT_MARKER)):
            layout_marker = open(
                os.path.join(self.base_dir, LAYOUT_MARKER), 'wb')
            layout_marker.write(self.layout_name)
        else:
            layout = open(os.path.join(self.base_dir, LAYOUT_MARKER), 'rb'
                          ).read().strip()
            if layout != self.layout_name:
                raise ValueError(
                    "Directory layout `%s` selected for blob directory %s, but "
                    "marker found for layout `%s`" %
                    (self.layout_name, self.base_dir, layout))

    def isSecure(self, path):
        """Ensure that (POSIX) path mode bits are 0700."""
        return (os.stat(path).st_mode & 077) == 0

    def checkSecure(self):
        if not self.isSecure(self.base_dir):
            log('Blob dir %s has insecure mode setting' % self.base_dir,
                level=logging.WARNING)

Then, the only thing you need to do is run chmod 700 var/blobstorage (owner can read, write and execute) in your installation directory.

Why this directory is created with a different setting (755) is a mystery to solve another day.

Tuesday, December 20, 2011

Hiding uninstall profiles using Grok

Tired of seeing your uninstall profile listed even when your package has not being installed yet?

If you have five.grok among the dependencies of your package in setup.py, you can put the following code in a setuphandlers.py file:

from five import grok

from Products.CMFPlone.interfaces import INonInstallable


class HiddenProfiles(grok.GlobalUtility):

    grok.implements(INonInstallable)
    grok.provides(INonInstallable)
    grok.name('your.package')

    def getNonInstallableProfiles(self):
        profiles = ['your.package:uninstall']
        return profiles

Remember that you need to Grok your package using the following line in your configure.zcml:

<grok:grok package="." />

This cool tip has been brought to you by Érico Andrei; enjoy it!

Friday, November 18, 2011

Max Keiser interviews Grateful Dead's John Perry Barlow about activism and open source

John Perry Barlow is a poet, essayist, retired rancher, political activist, former lyricist for the Grateful Dead and founding member of the Electronic Frontier Foundation.

Max Keiser interviews John Perry Barlow about activism and open source.

A must see!

Thursday, October 13, 2011

Cómo habilitar la selección y copia de texto en el sitio de El Universal

Hace un rato me topé con la novedad de que algunas páginas de El Universal no permiten seleccionar texto para copiarlo.

Al principio pensé que se trataba de algún script pero pronto descubrí que se era otra cosa: la inclusión en la hoja de estilo de la página de los seudoelementos -moz-user-select y -moz-user-focus.

Si usas Firefox, la solución es muy sencilla: crea un archivo userContent.css dentro la carpeta chrome de tu perfil y agrega las siguientes líneas:

* { -moz-user-select: auto !important }
* { -moz-user-focus: normal !important }


Reinicia tu navegador y listo.

Que nadie coarte tu derecho a compartir conocimiento.