Exemplo n.º 1
0
    def create_home_dir(self):
        from contenttypes.container import Directory, Home
        from core.database.postgres.permission import AccessRulesetToRule
        from core.permission import get_or_add_access_rule
        s = object_session(self)
        home_root = s.query(Home).one()
        homedir_name = self.login_name
        home = Directory(homedir_name)
        home_root.container_children.append(home)
        home.children.extend(create_special_user_dirs())
        # add access rules so only the user itself can access the home dir
        private_group = self.get_or_add_private_group()
        # we need the private group ID, it's set on flush by the DB
        s.flush()
        user_access_rule = get_or_add_access_rule(group_ids=[private_group.id])

        for access_type in (u"read", u"write", u"data"):
            ruleset = home.get_or_add_special_access_ruleset(access_type)
            arr = AccessRulesetToRule(rule=user_access_rule)
            ruleset.rule_assocs.append(arr)

        self.home_dir = home
        logg.info("created home dir for user '%s (id: %s)'", self.login_name,
                  self.id)
        return home
Exemplo n.º 2
0
def ruleset(session, users_and_groups_for_ruleset):
    users, groups = users_and_groups_for_ruleset
    rs = AccessRulesetFactory(name="not_rule")
    rule = AccessRule(group_ids=[g.id for g in groups] +
                      [u.get_or_add_private_group().id for u in users])
    rs.rule_assocs.append(AccessRulesetToRule(rule=rule))
    return rs
Exemplo n.º 3
0
    def runAction(self, node, op=""):
        """
        The actual proccessing of the node object takes place here.

        Read out the values of attrname and accesstype if any. Generate the
        ACL-rule, and save it.
        """
        l_date = node.get(self.get('attrname'))
        if l_date:
            if date.validateDateString(l_date):
                try:
                    node.set('updatetime',
                             date.format_date(date.parse_date(l_date)))
                    formated_date = date.format_date(date.parse_date(l_date),
                                                     "dd.mm.yyyy")
                    d = formated_date.split('.')
                    rule = get_or_add_defer_daterange_rule(
                        int(d[2]), int(d[1]), int(d[0]))

                    for access_type in self.get('accesstype').split(';'):
                        special_access_ruleset = node.get_or_add_special_access_ruleset(
                            ruletype=access_type)
                        special_access_ruleset.rule_assocs.append(
                            AccessRulesetToRule(rule=rule))

                    db.session.commit()

                except ValueError:
                    logg.exception(
                        "exception in workflow step defer, runAction failed")
Exemplo n.º 4
0
def migrate_access_entries():
    s = db.session
    # we need a "internal" ruleset for workflows that is empty
    workflow_ruleset = AccessRuleset(
        name=u"workflow",
        description=u"dummy access ruleset for workflow nodes")
    s.add(workflow_ruleset)
    access = s.execute("select * from mediatum_import.access").fetchall()
    for a in access:
        rulestr = a["rule"]
        ruleset = AccessRuleset(name=a["name"], description=a["description"])
        access_rules = convert_old_acl(rulestr)
        for rule, (invert, blocking) in access_rules:
            if rule.invert_group is None:
                rule.invert_group = False
            if rule.invert_subnet is None:
                rule.invert_subnet = False
            if rule.invert_date is None:
                rule.invert_date = False

            existing_rule = find_equivalent_access_rule(rule)

            if existing_rule:
                rule = existing_rule

            rule_assoc = AccessRulesetToRule(rule=rule,
                                             ruleset=ruleset,
                                             invert=invert,
                                             blocking=blocking)
            s.add(rule_assoc)
Exemplo n.º 5
0
def replace_or_add_defer_date(node, iso_date_old, iso_date_new, access_types=[u'read', u'data']):
    """
    examples:
        # set new date in the future (for read and data access)
        replace_or_add_defer_date(node, u"2016-11-03T00:00:00", u"2017-11-03T00:00:00")

        # remove existing rule
        replace_or_add_defer_date(node, u"2016-11-03T00:00:00", u"")

        # add new rule
        replace_or_add_defer_date(node, u"", u"2017-11-03T00:00:00")
    """

    if (not (iso_date_old or iso_date_new)) or (not access_types):
        print ("noting to be done")
        return

    import utils.date as date
    from psycopg2.extras import DateRange
    import datetime
    from core import AccessRule, AccessRulesetToRule, db

    q = db.query
    from core.permission import get_or_add_access_rule

    if iso_date_old:
        formatted_date_old = date.format_date(date.parse_date(iso_date_old), "dd.mm.yyyy")
        day_old, month_old, year_old = map(int, formatted_date_old.split('.'))
        dateranges_old = set([DateRange(datetime.date(year_old, month_old, day_old),
                                        datetime.date(9999, 12, 31), '[)')])
        # !!! exit if more than one rule for this daterange exists, should be fixed by looping through the nodes rules
        rule_old = q(AccessRule).filter_by(group_ids=None, dateranges=dateranges_old, subnets=None,
                                           invert_group=False, invert_date=False, invert_subnet=False).one()
        if not rule_old:
            raise ValueError('rule not found for old date {}'.format(iso_date_old))
        print("found old rule {}".format(rule_old.to_dict()))
    else:
        rule_old = None

    if iso_date_new:

        formatted_date_new = date.format_date(date.parse_date(iso_date_new), "dd.mm.yyyy")
        day_new, month_new, year_new = map(int, formatted_date_new.split('.'))
        dateranges_new = set([DateRange(datetime.date(year_new, month_new, day_new),
                                        datetime.date(9999, 12, 31), '[)')])

        rule_new = get_or_add_access_rule(dateranges=dateranges_new)
    else:
        rule_new = None

    for access_type in access_types:
        special_access_ruleset = node.get_or_add_special_access_ruleset(ruletype=access_type)
        if rule_old:
            arr_old = q(AccessRulesetToRule).filter_by(ruleset=special_access_ruleset, rule=rule_old).one()
            special_access_ruleset.rule_assocs.remove(arr_old)
        if rule_new:
            special_access_ruleset.rule_assocs.append(AccessRulesetToRule(rule=rule_new))
Exemplo n.º 6
0
def test_add_rules_to_node_special_ruleset(session, some_node):
    node = some_node
    srs = node.get_or_add_special_access_ruleset(u"read")
    r1 = AccessRule(group_ids=[1])
    srs.rule_assocs.append(AccessRulesetToRule(rule=r1))
    assert node.access_rule_assocs.first().rule is r1
    r2 = AccessRule(group_ids=[2])
    srs.rule_assocs.append(
        AccessRulesetToRule(rule=r2, blocking=True, invert=True))
    # check ruleset association
    nar2 = node.access_ruleset_assocs.first()
    assert nar2.ruleset is srs
    assert nar2.private == True
    # check rule association
    arr2 = node.access_rule_assocs[1]
    assert arr2.rule is r2
    assert arr2.ruletype == u"read"
    assert arr2.blocking == True
    assert arr2.invert == True
Exemplo n.º 7
0
def set_home_dir_permissions():
    users_with_home_dir = db.query(User).filter(User.home_dir_id != None)
    for user in users_with_home_dir:
        private_group = user.get_or_add_private_group()
        db.session.flush()
        assert private_group.id
        rule = AccessRule(group_ids=[private_group.id])

        for ruletype in (u"read", u"write", u"data"):
            special_access_ruleset = user.home_dir.get_or_add_special_access_ruleset(
                ruletype)
            special_access_ruleset.rule_assocs.append(
                AccessRulesetToRule(rule=rule))
Exemplo n.º 8
0
def test_delete_rule_from_node_special_ruleset(session, some_node):
    node = some_node
    q = session.query
    srs = node.get_or_add_special_access_ruleset(u"read")
    ruleset_name = srs.name
    r1 = AccessRule(group_ids=[1])
    arr = AccessRulesetToRule(rule=r1)
    srs.rule_assocs.append(arr)
    session.flush()
    srs.rule_assocs.remove(arr)
    assert node.access_rule_assocs.count() == 0
    # trigger should remove the special ruleset because it's empty now
    session.expunge_all()
    assert q(AccessRuleset).get(ruleset_name) is None
Exemplo n.º 9
0
def save_node_to_special_rules(nid_to_special_rules, ruletype):
    from core import Node
    logg.info("saving special %s rules for %d nodes", ruletype,
              len(nid_to_special_rules))
    for nid, rules_with_flags in iteritems(nid_to_special_rules):
        ruleset_assoc = _create_private_ruleset_assoc_for_nid(nid, ruletype)
        db.session.add(ruleset_assoc)
        rs = ruleset_assoc.ruleset
        assert rules_with_flags, "tried to save a special ruleset with no rules"
        for rule, (invert, blocking) in rules_with_flags:
            rs.rule_assocs.append(
                AccessRulesetToRule(rule=rule,
                                    invert=invert,
                                    blocking=blocking))
Exemplo n.º 10
0
 def create_ruleset_for_group(self, line):
     args = parse_argstring(self.create_ruleset_for_group, line)
     group_name = args.group_name
     usergroup = q(UserGroup).filter_by(name=group_name).scalar()
     if usergroup is None:
         print("usergroup {} does not exist, doing nothing!".format(group_name))
         return
     
     existing_ruleset = q(AccessRuleset).filter_by(name=group_name).scalar()
     if existing_ruleset is not None:
         print("ruleset with the name of the usergroup already exists, doing nothing!".format(group_name))
         return
     
     rule = get_or_add_access_rule(group_ids=[usergroup.id])
     ruleset = AccessRuleset(name=group_name, description=group_name)
     arr = AccessRulesetToRule(rule=rule)
     ruleset.rule_assocs.append(arr)
Exemplo n.º 11
0
 def on_model_change(self, form, usergroup, is_created):
     if is_created:
         """ create ruleset for group """
         existing_ruleset = q(AccessRuleset).filter_by(
             name=usergroup.name).scalar()
         if existing_ruleset is None:
             rule = get_or_add_access_rule(group_ids=[usergroup.id])
             ruleset = AccessRuleset(name=usergroup.name,
                                     description=usergroup.name)
             arr = AccessRulesetToRule(rule=rule)
             ruleset.rule_assocs.append(arr)
     """ add/remove access to Metadatatypes """
     for mt in q(Metadatatype):
         nrs_list = q(NodeToAccessRuleset).filter_by(nid=mt.id).filter_by(
             ruleset_name=usergroup.name).all()
         if mt in form.metadatatypes.data:
             if not nrs_list:
                 mt.access_ruleset_assocs.append(
                     NodeToAccessRuleset(ruleset_name=usergroup.name,
                                         ruletype=u'read'))
         else:
             for nrs in nrs_list:
                 mt.access_ruleset_assocs.remove(nrs)
Exemplo n.º 12
0
def getContent(req, ids):

    hidden_edit_functions_for_current_user = current_user.hidden_edit_functions
    if 'acls' in hidden_edit_functions_for_current_user:
        req.setStatus(httpstatus.HTTP_FORBIDDEN)
        return req.getTAL("web/edit/edit.html", {}, macro="access_error")

    if len(ids) != 1:  # should not happen
        req.setStatus(httpstatus.HTTP_FORBIDDEN)
        return req.getTAL("web/edit/modules/acls.html", {},
                          macro="acl_editor_error")

    # check write access to node
    idstr = ids[0]
    nid = long(idstr)
    node = q(Node).get(nid)
    if not node.has_write_access():
        req.setStatus(httpstatus.HTTP_FORBIDDEN)
        return req.getTAL("web/edit/edit.html", {}, macro="access_error")

    if "save" in req.params:
        logg.info("%r change access %r", current_user, idstr)
        if req.params.get("type") == "acl":

            for rule_type in rule_types:

                ruleset_names_from_request = [
                    rsn for rsn in req.params.get(u"left%s" %
                                                  rule_type, u"").split(u";")
                    if rsn.strip()
                ]

                inherited_ruleset_assocs, \
                own_ruleset_assocs, \
                special_ruleset, \
                special_rule_assocs = get_access_rules_info(node, rule_type)

                own_ruleset_names_not_private = [
                    r.ruleset_name for r in own_ruleset_assocs if not r.private
                ]

                to_be_removed_rulesets = set(
                    own_ruleset_names_not_private) - set(
                        ruleset_names_from_request)
                to_be_added_rulesets = set(ruleset_names_from_request) - set(
                    own_ruleset_names_not_private) - {'__special_rule__'}

                if to_be_removed_rulesets:
                    msg = "node %r: %r removing rulesets %r" % (
                        node, rule_type, to_be_removed_rulesets)
                    logg.info(msg)
                    for ruleset_name in to_be_removed_rulesets:
                        node.access_ruleset_assocs.filter_by(
                            ruleset_name=ruleset_name,
                            ruletype=rule_type).delete()

                if to_be_added_rulesets:
                    msg = "node %r: %r adding rulesets %r" % (
                        node, rule_type, to_be_added_rulesets)
                    logg.info(msg)
                    for ruleset_name in to_be_added_rulesets:
                        node.access_ruleset_assocs.append(
                            NodeToAccessRuleset(ruleset_name=ruleset_name,
                                                ruletype=rule_type))

            db.session.commit()

        if req.params.get("type") == "user":

            for rule_type in rule_types:

                user_ids_from_request = [
                    rsn for rsn in req.params.get(u"leftuser%s" %
                                                  rule_type, u"").split(u";")
                    if rsn.strip()
                ]

                special_ruleset = node.get_special_access_ruleset(rule_type)
                if special_ruleset:
                    special_rule_assocs = special_ruleset.rule_assocs
                else:
                    special_rule_assocs = []

                special_access_rules = [ra.rule for ra in special_rule_assocs]
                user_test_results = [
                    decider_is_private_user_group_access_rule(ar)
                    for ar in special_access_rules
                ]
                uids = [u.id for u in user_test_results if isinstance(u, User)]

                uids_to_remove = list(set(uids) - set(user_ids_from_request))
                uids_to_add = list(set(user_ids_from_request) - set(uids))
                if uids_to_add and not special_ruleset:  # in this case uids_to_remove will be empty
                    special_ruleset = node.get_or_add_special_access_ruleset(
                        rule_type)
                    special_rule_assocs = special_ruleset.rule_assocs

                for uid in uids_to_add:
                    user = q(User).get(uid)
                    access_rule = get_or_add_private_access_rule_for_user(user)
                    rule_assoc = AccessRulesetToRule(
                        rule=access_rule,
                        #ruleset=special_ruleset,
                        invert=False,
                        blocking=False)
                    special_rule_assocs.append(rule_assoc)

                # remove uids_to_remove *after* having added uids_to_add: a trigger may delete empty rulesets
                for uid in uids_to_remove:

                    user = q(User).get(uid)
                    access_rule = get_or_add_private_access_rule_for_user(user)

                    for rule_assoc in special_rule_assocs:
                        if rule_assoc.rule_id == access_rule.id:
                            db.session.delete(rule_assoc)

                    db.session.flush()

            db.session.commit()

    action = req.params.get("action", "")

    retacl = ""
    if not action:

        rulesetnamelist = [
            t[0]
            for t in q(AccessRuleset.name).order_by(AccessRuleset.name).all()
        ]
        private_ruleset_names = [
            t[0] for t in q(NodeToAccessRuleset.ruleset_name).filter_by(
                private=True).all()
        ]
        rulesetnamelist = [
            rulesetname for rulesetname in rulesetnamelist
            if not rulesetname in private_ruleset_names
        ]

        for rule_type in rule_types:
            inherited_ruleset_assocs, \
            own_ruleset_assocs, \
            special_ruleset, special_rule_assocs = get_access_rules_info(node, rule_type)
            retacl += req.getTAL(
                "web/edit/modules/acls.html",
                makeList(
                    req,
                    own_ruleset_assocs,  #not_inherited_ruleset_names[rule_type],  # rights
                    inherited_ruleset_assocs,  #inherited_ruleset_names[rule_type],  # readonlyrights
                    special_ruleset,  #additional_rules_inherited[rule_type],
                    special_rule_assocs,  #additional_rules_not_inherited[rule_type],
                    rulesetnamelist,
                    private_ruleset_names,
                    rule_type=rule_type),
                macro="edit_acls_selectbox")

    if action == 'get_userlist':  # load additional rights by ajax

        rulesetnamelist = [
            t[0]
            for t in q(AccessRuleset.name).order_by(AccessRuleset.name).all()
        ]
        private_ruleset_names = [
            t[0] for t in q(NodeToAccessRuleset.ruleset_name).filter_by(
                private=True).all()
        ]
        rulesetnamelist = [
            rulesetname for rulesetname in rulesetnamelist
            if not rulesetname in private_ruleset_names
        ]

        retuser = ""
        for rule_type in rule_types:
            inherited_ruleset_assocs, \
            own_ruleset_assocs, \
            special_ruleset, special_rule_assocs = get_access_rules_info(node, rule_type)
            retuser += req.getTAL(
                "web/edit/modules/acls.html",
                makeUserList(
                    req,
                    own_ruleset_assocs,  # not_inherited_ruleset_names[rule_type],  # rights
                    inherited_ruleset_assocs,  # inherited_ruleset_names[rule_type],  # readonlyrights
                    special_ruleset,  # additional_rules_inherited[rule_type],
                    special_rule_assocs,  # additional_rules_not_inherited[rule_type],
                    rulesetnamelist,
                    private_ruleset_names,
                    rule_type=rule_type),
                macro="edit_acls_userselectbox")
        req.write(retuser)
        return ""

    runsubmit = "\nfunction runsubmit(){\n"
    for rule_type in rule_types:
        runsubmit += "\tmark(document.myform.left" + rule_type + ");\n"
        runsubmit += "\tmark(document.myform.leftuser" + rule_type + ");\n"
    runsubmit += "\tdocument.myform.submit();\n}\n"

    return req.getTAL("web/edit/modules/acls.html", {
        "runsubmit": runsubmit,
        "idstr": idstr,
        "contentacl": retacl,
        "adminuser": current_user.is_admin
    },
                      macro="edit_acls")
Exemplo n.º 13
0
def init_database_values(s, default_admin_password=None):
    from core import config
    from core import User, UserGroup, AuthenticatorInfo, AccessRule
    from core.systemtypes import Root, Metadatatypes, Mappings, Searchmasks
    from contenttypes import Collections, Home
    from workflow.workflow import Workflows
    from core.auth import INTERNAL_AUTHENTICATOR_KEY, create_password_hash
    from core.permission import get_or_add_access_rule
    from core.database.postgres.permission import AccessRuleset, AccessRulesetToRule, NodeToAccessRule
    from web.admin.adminutils import adminNavigation
    from core.xmlnode import readNodeXML
    """
    :type s: Session
    """

    # every database must have an everybody rule
    everybody_rule = AccessRule()
    s.add(everybody_rule)

    # node tree setup
    root = Root(u"root", id=1)
    metadatatypes = Metadatatypes(u"metadatatypes", id=3)
    workflows = Workflows(u"workflows", id=4)
    mappings = Mappings(u"mappings", id=9)
    collections = Collections(u"collections", schema=u"collection", id=10)
    collections.attrs[u"label"] = u"Collections"
    collections.access_rule_assocs.append(
        NodeToAccessRule(ruletype=u"read", rule=everybody_rule))
    home = Home(u"home", id=11)
    searchmasks = Searchmasks(u"searchmasks", id=15)

    root.children.extend(
        [metadatatypes, workflows, mappings, collections, home, searchmasks])

    # finally, add node tree. All nodes will be added automatically
    s.add(root)
    # activate menuitems metadatatypes, workflows etc.
    adminNavigation()
    logg.info(u"loaded initial values")

    # default users and groups setup
    # add internal authenticator
    auth_type, auth_name = INTERNAL_AUTHENTICATOR_KEY
    internal_auth = AuthenticatorInfo(id=0,
                                      auth_type=auth_type,
                                      name=auth_name)

    default_admin_password = config.get(u"user.default_admin_password",
                                        default_admin_password)
    if default_admin_password:
        admin_hash, admin_salt = create_password_hash(default_admin_password)
    else:
        # admin user cannot login when no default_admin_password is set
        admin_hash, admin_salt = None, None

    adminuser = User(login_name=config.get(u"user.adminuser", u"admin"),
                     password_hash=admin_hash,
                     salt=admin_salt,
                     email=u"admin@mediatum",
                     authenticator_info=internal_auth,
                     can_change_password=True)

    guestuser = User(login_name=config.get_guest_name(),
                     email=u"guest@mediatum",
                     authenticator_info=internal_auth)

    admingroup = UserGroup(name=config.get(u"user.admingroup",
                                           u"administration"),
                           is_workflow_editor_group=True,
                           is_editor_group=True,
                           is_admin_group=True)
    admingroup.users.append(adminuser)
    s.add(admingroup)
    guestgroup = UserGroup(name=u"guests")
    guestgroup.users.append(guestuser)
    s.add(guestgroup)

    # add rules for admingroup, guestgroup
    for usergroup in [admingroup, guestgroup]:
        rule = get_or_add_access_rule(group_ids=[usergroup.id])
        ruleset = AccessRuleset(name=usergroup.name,
                                description=usergroup.name)
        arr = AccessRulesetToRule(rule=rule)
        ruleset.rule_assocs.append(arr)

    # add example metadatatypes
    example_path_collection = os.path.join(config.basedir,
                                           u"examples/content/collection.xml")
    metadatatype_collection = readNodeXML(example_path_collection)

    example_path_directory = os.path.join(config.basedir,
                                          u"examples/content/directory.xml")
    metadatatype_directory = readNodeXML(example_path_directory)

    example_path_image = os.path.join(config.basedir,
                                      u"examples/content/image.xml")
    metadatatype_image = readNodeXML(example_path_image)

    example_path_document = os.path.join(config.basedir,
                                         u"examples/content/document.xml")
    metadatatype_document = readNodeXML(example_path_document)

    metadatatypes.children.extend([
        metadatatype_collection, metadatatype_directory, metadatatype_image,
        metadatatype_document
    ])
Exemplo n.º 14
0
    def show_workflow_step(self, req):
        typenames = self.get("newnodetype").split(";")
        wfnode = self.parents[0]
        redirect = ""
        message = ""

        # check existence of metadata types listed in the definition of the start node
        mdts = q(Metadatatypes).one()
        for schema in typenames:
            if not mdts.children.filter_by(
                    name=schema.strip().split("/")[-1]).scalar():
                return ('<i>%s: %s </i>') % (schema,
                                             t(lang(req), "permission_denied"))

        if "workflow_start" in req.params:
            switch_language(req, req.params.get('workflow_language'))
            content_class = Node.get_class_for_typestring(
                req.params.get('selected_schema').split('/')[0])
            node = content_class(
                name=u'',
                schema=req.params.get('selected_schema').split('/')[1])
            self.children.append(node)

            # create user group named '_workflow' if it doesn't exist
            workflow_group = q(UserGroup).filter_by(name=u'_workflow').scalar()
            if workflow_group is None:
                workflow_group = UserGroup(
                    name=u'_workflow',
                    description=u'internal dummy group for nodes in workflows')
                db.session.add(workflow_group)

            # create access rule with '_workflow' user group
            workflow_rule = get_or_add_access_rule(
                group_ids=[workflow_group.id])

            special_access_ruleset = node.get_or_add_special_access_ruleset(
                ruletype=u'read')
            special_access_ruleset.rule_assocs.append(
                AccessRulesetToRule(rule=workflow_rule))

            node.set("creator", "workflow-" + self.parents[0].name)
            node.set("creationtime", date.format_date())
            node.set(
                "system.wflanguage",
                req.params.get('workflow_language',
                               req.Cookies.get('language')))
            node.set("key", mkKey())
            node.set("system.key", node.get("key"))  # initial key identifier
            req.session["key"] = node.get("key")
            db.session.commit()
            return self.forwardAndShow(node, True, req)

        elif "workflow_start_auth" in req.params:  # auth node by id and key
            try:
                node = q(Node).get(req.params.get('nodeid'))

                # startkey, but protected
                if node.get('system.key') == req.params.get(
                        'nodekey'
                ) and node.get('key') != req.params.get('nodekey'):
                    message = "workflow_start_err_protected"
                elif node.get('key') == req.params.get('nodekey'):
                    redirect = "/pnode?id=%s&key=%s" % (node.id,
                                                        node.get('key'))
                else:
                    message = "workflow_start_err_wrongkey"
            except:
                logg.exception(
                    "exception in workflow step start (workflow_start_auth)")
                message = "workflow_start_err_wrongkey"

        types = []
        for a in typenames:
            if a:
                m = getMetaType(a)
                # we could now check m.isActive(), but for now let's
                # just take all specified metatypes, so that edit area
                # and workflow are independent on this
                types += [(m, a)]
        cookie_error = t(lang(req), "Your browser doesn't support cookies")

        js = """
        <script language="javascript">
        function cookie_test() {
            if (document.cookie=="")
                document.cookie = "CookieTest=Erfolgreich";
            if (document.cookie=="") {
                alert("%s");
            }
        }
        cookie_test();
        </script>""" % cookie_error

        return req.getTAL("workflow/start.html", {
            'types': types,
            'id': self.id,
            'js': js,
            'starttext': self.get('starttext'),
            'languages': self.parents[0].getLanguages(),
            'currentlang': lang(req),
            'sidebartext': self.getSidebarText(lang(req)),
            'redirect': redirect,
            'message': message,
            'allowcontinue': self.get('allowcontinue'),
            "csrf": req.csrf_token.current_token,
        },
                          macro="workflow_start")