Пример #1
0
 def validate(self, relation):
     rls = RelationsSystem(self.env)
     existing_relations = rls._select_relations(relation.source,
                                                relation.type)
     if existing_relations:
         raise ValidationError(
             "%s can only have one %s" %
             (relation.source, self.render_relation_type(relation.type)))
Пример #2
0
 def validate(self, relation):
     rls = RelationsSystem(self.env)
     existing_relations = rls._select_relations(relation.source,
                                                relation.type)
     if existing_relations:
         raise ValidationError(
             "%s can only have one %s" % (
                 relation.source,
                 self.render_relation_type(relation.type)
             ))
Пример #3
0
 def validate(self, relation):
     rls = RelationsSystem(self.env)
     existing_relations = rls._select_relations(resource_type=relation.type,
                                                destination=relation.destination)
     if existing_relations:
         raise ValidationError(
             tag_("Another resource is already related to %(destination)s "
                  "with %(relation)s relation.",
                  destination=tag.em(relation.destination),
                  relation=tag.b(self.render_relation_type(relation.type)))
         )
Пример #4
0
 def get_ticket_relations(self, ticket):
     grouped_relations = {}
     relsys = RelationsSystem(self.env)
     reltypes = relsys.get_relation_types()
     trs = TicketRelationsSpecifics(self.env)
     for r in relsys.get_relations(ticket):
         r['desthref'] = get_resource_url(self.env, r['destination'],
                                          self.env.href)
         r['destticket'] = trs._create_ticket_by_full_id(r['destination'])
         grouped_relations.setdefault(reltypes[r['type']], []).append(r)
     return grouped_relations
Пример #5
0
 def get_ticket_relations(self, ticket):
     grouped_relations = {}
     relsys = RelationsSystem(self.env)
     reltypes = relsys.get_relation_types()
     trs = TicketRelationsSpecifics(self.env)
     for r in relsys.get_relations(ticket):
         r['desthref'] = get_resource_url(self.env, r['destination'],
             self.env.href)
         r['destticket'] = trs._create_ticket_by_full_id(r['destination'])
         grouped_relations.setdefault(reltypes[r['type']], []).append(r)
     return grouped_relations
Пример #6
0
 def remove_relations(self, req, rellist):
     relsys = RelationsSystem(self.env)
     for relid in rellist:
         relation = Relation.load_by_relation_id(self.env, relid)
         resource = ResourceIdSerializer.get_resource_by_id(
             relation.destination)
         if 'TICKET_MODIFY' in req.perm(resource):
             relsys.delete(relid)
         else:
             add_warning(req,
                 _('Not enough permissions to remove relation "%s"' % relid))
Пример #7
0
 def remove_relations(self, req, rellist):
     relsys = RelationsSystem(self.env)
     for relid in rellist:
         relation = Relation.load_by_relation_id(self.env, relid)
         resource = \
             ResourceIdSerializer.get_resource_by_id(relation.destination)
         if 'TICKET_MODIFY' in req.perm(resource):
             relsys.delete(relid)
         else:
             add_warning(req, _('Insufficient permissions to remove '
                                'relation "%(relation)s"', relation=relid))
Пример #8
0
 def validate(self, relation):
     rls = RelationsSystem(self.env)
     existing_relations = \
         rls._select_relations(resource_type=relation.type,
                               destination=relation.destination)
     if existing_relations:
         raise ValidationError(
             tag_("Another resource is already related to %(destination)s "
                  "with %(relation)s relation.",
                  destination=tag.em(relation.destination),
                  relation=tag.b(self.render_relation_type(relation.type)))
         )
Пример #9
0
    def setUp(self, enabled=()):
        env = EnvironmentStub(
            default_data=True,
            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
                    list(enabled))
        )
        env.config.set('bhrelations', 'global_validators',
                       'NoSelfReferenceValidator,ExclusiveValidator,'
                       'BlockerValidator')
        env.config.set('bhrelations', 'duplicate_relation',
                       'duplicateof')
        config_name = RELATIONS_CONFIG_NAME
        env.config.set(config_name, 'dependency',
                       ','.join([DEPENDS_ON, DEPENDENCY_OF]))
        env.config.set(config_name, 'dependency.validators',
                       'NoCycles,SingleProduct')
        env.config.set(config_name, 'dependson.blocks', 'true')
        env.config.set(config_name, 'parent_children',
                       ','.join([PARENT, CHILD]))
        env.config.set(config_name, 'parent_children.validators',
                       'OneToMany,SingleProduct,NoCycles')
        env.config.set(config_name, 'children.label', 'Overridden')
        env.config.set(config_name, 'parent.copy_fields',
                       'summary, foo')
        env.config.set(config_name, 'parent.exclusive', 'true')
        env.config.set(config_name, 'multiproduct_relation',
                       ','.join([MULTIPRODUCT_REL, MULTIPRODUCT_BACKREL]))
        env.config.set(config_name, 'oneway', REFERS_TO)
        env.config.set(config_name, 'duplicate',
                       ','.join([DUPLICATE_OF, DUPLICATED_BY]))
        env.config.set(config_name, 'duplicate.validators', 'ReferencesOlder')
        env.config.set(config_name, 'duplicateof.label', 'is a duplicate of')
        env.config.set(config_name, 'duplicatedby.label', 'duplicates')
        env.config.set(config_name, 'blocker', ','.join([BLOCKED_BY, BLOCKS]))
        env.config.set(config_name, 'blockedby.blocks', 'true')

        self.global_env = env
        self._upgrade_mp(self.global_env)
        self._setup_test_log(self.global_env)
        self._load_product_from_data(self.global_env, self.default_product)
        self.env = ProductEnvironment(self.global_env, self.default_product)

        self.req = Mock(href=self.env.href, authname='anonymous', tz=utc,
                        args=dict(action='dummy'),
                        locale=locale_en, lc_time=locale_en,
                        chrome={'warnings': []})
        self.req.perm = MockPerm()
        self.relations_system = RelationsSystem(self.env)
        self._upgrade_env()
Пример #10
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            ticket = data['ticket']
            rls = RelationsSystem(self.env)
            try:
                resid = ResourceIdSerializer.get_resource_id_from_instance(
                    self.env, ticket)
            except ValueError:
                resid = None

            if rls.duplicate_relation_type and resid is not None:
                duplicate_relations = \
                    rls._select_relations(resid, rls.duplicate_relation_type)
                if duplicate_relations:
                    data['ticket_duplicate_of'] = \
                        duplicate_relations[0].destination
        return template, data, content_type
Пример #11
0
    def pre_process(self, doc):
        resource_id = ':'.join([
            doc.get('product', ''), doc.get('type', ''), doc.get('id')])

        try:
            rls = RelationsSystem(self.env)
            relations = []
            for relation in rls._select_relations(resource_id):
                relations.extend(self._format_relations(relation))
            doc['relations'] = ','.join(relations)
        except self.env.db_exc.OperationalError:
            # If bhrelations and bhsearch are installed at the same time and
            # bhsearch is upgraded before bhrelations, table
            # bloodhound_relations will be missing, thus causing the
            # OperationalError. As this means that the relations do not
            # exist yet, just skip indexing them.
            self.log.debug("Not indexing relations for %s", resource_id)
Пример #12
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            ticket = data['ticket']
            rls = RelationsSystem(self.env)
            try:
                resid = ResourceIdSerializer.get_resource_id_from_instance(
                    self.env, ticket)
            except ValueError:
                resid = None

            if rls.duplicate_relation_type and resid is not None:
                duplicate_relations = \
                    rls._select_relations(resid, rls.duplicate_relation_type)
                if duplicate_relations:
                    data['ticket_duplicate_of'] = \
                        duplicate_relations[0].destination
        return template, data, content_type
Пример #13
0
    def validate(self, relation):
        """If a path exists from relation's destination to its source,
         adding the relation will create a cycle.
         """
        rls = RelationsSystem(self.env)
        if not rls.is_blocker(relation.type):
            relation = rls.get_reverted_relation(relation)
        if not relation or not rls.is_blocker(relation.type):
            return

        blockers = ','.join(b for b, is_blocker in rls._blockers.items()
                            if is_blocker)

        path = self._find_path(relation.source, relation.destination, blockers)
        if path:
            cycle_str = map(self.get_resource_name, path)
            error = 'Cycle in ' '%s' ': %s' % (self.render_relation_type(
                relation.type), ' -> '.join(cycle_str))
            error = ValidationError(error)
            error.failed_ids = path
            raise error
Пример #14
0
    def validate(self, relation):
        """Prevents adding a cyclical blocker relation.
         """
        rls = RelationsSystem(self.env)
        if not rls.is_blocker(relation.type):
            relation = rls.get_reverted_relation(relation)
        if not relation or not rls.is_blocker(relation.type):
            return

        blockers = ','.join(b for b, is_blocker in rls._blockers.items()
                            if is_blocker)

        path = self._find_path(relation.source,
                               relation.destination,
                               blockers)
        if path:
            cycle_str = map(self.get_resource_name, path)
            error = 'Cycle in ''%s'': %s' % (
                self.render_relation_type(relation.type),
                ' -> '.join(cycle_str))
            error = ValidationError(error)
            error.failed_ids = path
            raise error
Пример #15
0
    def setUp(self, enabled=()):
        env = EnvironmentStub(
            default_data=True,
            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
                    list(enabled))
        )
        env.config.set('bhrelations', 'global_validators',
                       'NoSelfReferenceValidator,ExclusiveValidator,'
                       'BlockerValidator')
        env.config.set('bhrelations', 'duplicate_relation',
                       'duplicateof')
        config_name = RELATIONS_CONFIG_NAME
        env.config.set(config_name, 'dependency',
                       ','.join([DEPENDS_ON, DEPENDENCY_OF]))
        env.config.set(config_name, 'dependency.validators',
                       'NoCycles,SingleProduct')
        env.config.set(config_name, 'dependson.blocks', 'true')
        env.config.set(config_name, 'parent_children',
                       ','.join([PARENT, CHILD]))
        env.config.set(config_name, 'parent_children.validators',
                       'OneToMany,SingleProduct,NoCycles')
        env.config.set(config_name, 'children.label', 'Overridden')
        env.config.set(config_name, 'parent.copy_fields',
                       'summary, foo')
        env.config.set(config_name, 'parent.exclusive', 'true')
        env.config.set(config_name, 'multiproduct_relation',
                       ','.join([MULTIPRODUCT_REL, MULTIPRODUCT_BACKREL]))
        env.config.set(config_name, 'oneway', REFERS_TO)
        env.config.set(config_name, 'duplicate',
                       ','.join([DUPLICATE_OF, DUPLICATED_BY]))
        env.config.set(config_name, 'duplicate.validators', 'ReferencesOlder')
        env.config.set(config_name, 'duplicateof.label', 'is a duplicate of')
        env.config.set(config_name, 'duplicatedby.label', 'duplicates')
        env.config.set(config_name, 'blocker', ','.join([BLOCKED_BY, BLOCKS]))
        env.config.set(config_name, 'blockedby.blocks', 'true')

        self.global_env = env
        self._upgrade_mp(self.global_env)
        self._setup_test_log(self.global_env)
        self._load_product_from_data(self.global_env, self.default_product)
        self.env = ProductEnvironment(self.global_env, self.default_product)

        self.req = Mock(href=self.env.href, authname='anonymous', tz=utc,
                        args=dict(action='dummy'),
                        locale=locale_en, lc_time=locale_en,
                        chrome={'warnings': []})
        self.req.perm = MockPerm()
        self.relations_system = RelationsSystem(self.env)
        self._upgrade_env()
Пример #16
0
    def validate(self, relation):
        """If a path of exclusive type exists between source and destination,
        adding a relation is not allowed.
        """
        rls = RelationsSystem(self.env)
        source, destination = relation.source, relation.destination

        for exclusive_type in rls._exclusive:
            path = (self._find_path(source, destination, exclusive_type)
                    or self._find_path(destination, source, exclusive_type))
            if path:
                raise ValidationError(
                    "Cannot add relation %s, source and destination "
                    "are connected with %s relation." % (
                        self.render_relation_type(relation.type),
                        self.render_relation_type(exclusive_type),
                    )
                )
        if relation.type in rls._exclusive:
            d_ancestors = self._ancestors(destination, exclusive_type)
            d_ancestors.add(destination)
            s_descendants = self._descendants(source, exclusive_type)
            s_descendants.add(source)
            query = """
                SELECT source, destination, type
                  FROM bloodhound_relations
                 WHERE (source in (%(s_ancestors)s)
                        AND destination in (%(d_descendants)s))
                    OR
                       (source in (%(d_descendants)s)
                        AND destination in (%(s_ancestors)s))
            """ % dict(
                s_ancestors=', '.join("'%s'" % n for n in d_ancestors),
                d_descendants=', '.join("'%s'" % n for n in s_descendants))
            conflicting_relations = list(self.env.db_query(query))
            if conflicting_relations:
                raise ValidationError(
                    "Connecting %s and %s with relation %s "
                    "would make the following relations invalid:\n"
                    "%s" % (
                        source,
                        destination,
                        self.render_relation_type(relation.type),
                        '\n'.join(map(str, conflicting_relations))
                    )
                )
Пример #17
0
    def setUp(self, enabled=()):
        env = EnvironmentStub(
            default_data=True,
            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
                    list(enabled)))
        env.config.set(
            'bhrelations', 'global_validators',
            'NoSelfReferenceValidator,ExclusiveValidator,'
            'BlockerValidator')
        env.config.set('bhrelations', 'duplicate_relation', 'duplicateof')
        config_name = RelationsSystem.RELATIONS_CONFIG_NAME
        env.config.set(config_name, 'dependency', 'dependson,dependent')
        env.config.set(config_name, 'dependency.validators',
                       'NoCycles,SingleProduct')
        env.config.set(config_name, 'dependson.blocks', 'true')
        env.config.set(config_name, 'parent_children', 'parent,children')
        env.config.set(config_name, 'parent_children.validators',
                       'OneToMany,SingleProduct,NoCycles')
        env.config.set(config_name, 'children.label', 'Overridden')
        env.config.set(config_name, 'parent.copy_fields', 'summary, foo')
        env.config.set(config_name, 'parent.exclusive', 'true')
        env.config.set(config_name, 'multiproduct_relation', 'mprel,mpbackrel')
        env.config.set(config_name, 'oneway', 'refersto')
        env.config.set(config_name, 'duplicate', 'duplicateof,duplicatedby')
        env.config.set(config_name, 'duplicate.validators', 'ReferencesOlder')
        env.config.set(config_name, 'duplicateof.label', 'is a duplicate of')
        env.config.set(config_name, 'duplicatedby.label', 'duplicates')
        env.config.set(config_name, 'blocker', 'blockedby,blocks')
        env.config.set(config_name, 'blockedby.blocks', 'true')

        self.global_env = env
        self._upgrade_mp(self.global_env)
        self._setup_test_log(self.global_env)
        self._load_product_from_data(self.global_env, self.default_product)
        self.env = ProductEnvironment(self.global_env, self.default_product)

        self.req = Mock(href=self.env.href,
                        authname='anonymous',
                        tz=utc,
                        args=dict(action='dummy'),
                        locale=locale_en,
                        lc_time=locale_en)
        self.req.perm = MockPerm()
        self.relations_system = RelationsSystem(self.env)
        self._upgrade_env()
Пример #18
0
class BaseRelationsTestCase(MultiproductTestCase):
    def setUp(self, enabled=()):
        env = EnvironmentStub(
            default_data=True,
            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
                    list(enabled))
        )
        env.config.set('bhrelations', 'global_validators',
                       'NoSelfReferenceValidator,ExclusiveValidator,'
                       'BlockerValidator')
        env.config.set('bhrelations', 'duplicate_relation',
                       'duplicateof')
        config_name = RELATIONS_CONFIG_NAME
        env.config.set(config_name, 'dependency',
                       ','.join([DEPENDS_ON, DEPENDENCY_OF]))
        env.config.set(config_name, 'dependency.validators',
                       'NoCycles,SingleProduct')
        env.config.set(config_name, 'dependson.blocks', 'true')
        env.config.set(config_name, 'parent_children',
                       ','.join([PARENT, CHILD]))
        env.config.set(config_name, 'parent_children.validators',
                       'OneToMany,SingleProduct,NoCycles')
        env.config.set(config_name, 'children.label', 'Overridden')
        env.config.set(config_name, 'parent.copy_fields',
                       'summary, foo')
        env.config.set(config_name, 'parent.exclusive', 'true')
        env.config.set(config_name, 'multiproduct_relation',
                       ','.join([MULTIPRODUCT_REL, MULTIPRODUCT_BACKREL]))
        env.config.set(config_name, 'oneway', REFERS_TO)
        env.config.set(config_name, 'duplicate',
                       ','.join([DUPLICATE_OF, DUPLICATED_BY]))
        env.config.set(config_name, 'duplicate.validators', 'ReferencesOlder')
        env.config.set(config_name, 'duplicateof.label', 'is a duplicate of')
        env.config.set(config_name, 'duplicatedby.label', 'duplicates')
        env.config.set(config_name, 'blocker', ','.join([BLOCKED_BY, BLOCKS]))
        env.config.set(config_name, 'blockedby.blocks', 'true')

        self.global_env = env
        self._upgrade_mp(self.global_env)
        self._setup_test_log(self.global_env)
        self._load_product_from_data(self.global_env, self.default_product)
        self.env = ProductEnvironment(self.global_env, self.default_product)

        self.req = Mock(href=self.env.href, authname='anonymous', tz=utc,
                        args=dict(action='dummy'),
                        locale=locale_en, lc_time=locale_en,
                        chrome={'warnings': []})
        self.req.perm = MockPerm()
        self.relations_system = RelationsSystem(self.env)
        self._upgrade_env()

    def tearDown(self):
        self.global_env.reset_db()

    def _upgrade_env(self):
        environment_setup = EnvironmentSetup(self.env)
        try:
            environment_setup.upgrade_environment(self.env.db_transaction)
        except self.env.db_exc.OperationalError:
            # table remains but database version is deleted
            pass

    @classmethod
    def _insert_ticket(cls, env, summary, **kw):
        """Helper for inserting a ticket into the database"""
        ticket = Ticket(env)
        ticket["summary"] = summary
        for k, v in kw.items():
            ticket[k] = v
        return ticket.insert()

    def _insert_and_load_ticket(self, summary, **kw):
        return Ticket(self.env, self._insert_ticket(self.env, summary, **kw))

    def _insert_and_load_ticket_with_env(self, env, summary, **kw):
        return Ticket(env, self._insert_ticket(env, summary, **kw))

    def add_relation(self, source, reltype, destination, *args, **kwargs):
        return self.relations_system.add(source, destination, reltype, *args, **kwargs)

    def get_relations(self, ticket):
        return self.relations_system.get_relations(ticket)

    def delete_relation(self, relation):
        self.relations_system.delete(relation["relation_id"])
Пример #19
0
    def process_request(self, req):
        tid = req.args.get('id')
        if not tid:
            raise TracError(_('No ticket id provided.'))

        try:
            ticket = Ticket(self.env, tid)
        except ValueError:
            raise TracError(_('Invalid ticket id.'))

        req.perm.require('TICKET_VIEW')
        relsys = RelationsSystem(self.env)

        data = {
            'relation': {},
        }
        if req.method == 'POST':
            # for modifying the relations TICKET_MODIFY is required for
            # both the source and the destination tickets
            req.perm.require('TICKET_MODIFY')

            if 'remove' in req.args:
                rellist = req.args.get('sel')
                if rellist:
                    if isinstance(rellist, basestring):
                        rellist = [rellist, ]
                    self.remove_relations(req, rellist)
            elif 'add' in req.args:
                relation = dict(
                    destination=req.args.get('dest_tid', ''),
                    type=req.args.get('reltype', ''),
                    comment=req.args.get('comment', ''),
                )
                try:
                    trs = TicketRelationsSpecifics(self.env)
                    dest_ticket = trs.find_ticket(relation['destination'])
                except NoSuchTicketError:
                    data['error'] = _('Invalid ticket ID.')
                else:
                    req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id))

                    try:
                        dbrel = relsys.add(ticket, dest_ticket,
                            relation['type'],
                            relation['comment'],
                            req.authname)
                    except NoSuchTicketError:
                        data['error'] = _('Invalid ticket ID.')
                    except UnknownRelationType:
                        data['error'] = _('Unknown relation type.')
                    except ValidationError as ex:
                        data['error'] = ex.message
                    else:
                        # Notify
                        try:
                            self.notify_relation_changed(dbrel)
                        except Exception, e:
                            self.log.error("Failure sending notification on"
                                           "creation of relation: %s",
                                           exception_to_unicode(e))
                            add_warning(req, _("The relation has been added, but an "
                                               "error occurred while sending"
                                               "notifications: " "%(message)s",
                                               message=to_unicode(e)))

                if 'error' in data:
                    data['relation'] = relation
            else:
                raise TracError(_('Invalid operation.'))
Пример #20
0
class BaseRelationsTestCase(MultiproductTestCase):
    def setUp(self, enabled=()):
        env = EnvironmentStub(
            default_data=True,
            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
                    list(enabled))
        )
        env.config.set('bhrelations', 'global_validators',
                       'NoSelfReferenceValidator,ExclusiveValidator,'
                       'BlockerValidator')
        env.config.set('bhrelations', 'duplicate_relation',
                       'duplicateof')
        config_name = RELATIONS_CONFIG_NAME
        env.config.set(config_name, 'dependency',
                       ','.join([DEPENDS_ON, DEPENDENCY_OF]))
        env.config.set(config_name, 'dependency.validators',
                       'NoCycles,SingleProduct')
        env.config.set(config_name, 'dependson.blocks', 'true')
        env.config.set(config_name, 'parent_children',
                       ','.join([PARENT, CHILD]))
        env.config.set(config_name, 'parent_children.validators',
                       'OneToMany,SingleProduct,NoCycles')
        env.config.set(config_name, 'children.label', 'Overridden')
        env.config.set(config_name, 'parent.copy_fields',
                       'summary, foo')
        env.config.set(config_name, 'parent.exclusive', 'true')
        env.config.set(config_name, 'multiproduct_relation',
                       ','.join([MULTIPRODUCT_REL, MULTIPRODUCT_BACKREL]))
        env.config.set(config_name, 'oneway', REFERS_TO)
        env.config.set(config_name, 'duplicate',
                       ','.join([DUPLICATE_OF, DUPLICATED_BY]))
        env.config.set(config_name, 'duplicate.validators', 'ReferencesOlder')
        env.config.set(config_name, 'duplicateof.label', 'is a duplicate of')
        env.config.set(config_name, 'duplicatedby.label', 'duplicates')
        env.config.set(config_name, 'blocker', ','.join([BLOCKED_BY, BLOCKS]))
        env.config.set(config_name, 'blockedby.blocks', 'true')

        self.global_env = env
        self._upgrade_mp(self.global_env)
        self._setup_test_log(self.global_env)
        self._load_product_from_data(self.global_env, self.default_product)
        self.env = ProductEnvironment(self.global_env, self.default_product)

        self.req = Mock(href=self.env.href, authname='anonymous', tz=utc,
                        args=dict(action='dummy'),
                        locale=locale_en, lc_time=locale_en,
                        chrome={'warnings': []})
        self.req.perm = MockPerm()
        self.relations_system = RelationsSystem(self.env)
        self._upgrade_env()

    def tearDown(self):
        self.global_env.reset_db()

    def _upgrade_env(self):
        environment_setup = EnvironmentSetup(self.env)
        try:
            environment_setup.upgrade_environment(self.env.db_transaction)
        except self.env.db_exc.OperationalError:
            # table remains but database version is deleted
            pass

    @classmethod
    def _insert_ticket(cls, env, summary, **kw):
        """Helper for inserting a ticket into the database"""
        ticket = Ticket(env)
        ticket["summary"] = summary
        for k, v in kw.items():
            ticket[k] = v
        return ticket.insert()

    def _insert_and_load_ticket(self, summary, **kw):
        return Ticket(self.env, self._insert_ticket(self.env, summary, **kw))

    def _insert_and_load_ticket_with_env(self, env, summary, **kw):
        return Ticket(env, self._insert_ticket(env, summary, **kw))

    def add_relation(self, source, reltype, destination, *args, **kwargs):
        return self.relations_system.add(source, destination, reltype,
                                         *args, **kwargs)

    def get_relations(self, ticket):
        return self.relations_system.get_relations(ticket)

    def delete_relation(self, relation):
        self.relations_system.delete(relation["relation_id"])
Пример #21
0
    def process_request(self, req):
        tid = req.args.get('id')
        if not tid:
            raise TracError(_('No ticket id provided.'))

        try:
            ticket = Ticket(self.env, tid)
        except ValueError:
            raise TracError(_('Invalid ticket id.'))

        req.perm.require('TICKET_VIEW')
        relsys = RelationsSystem(self.env)

        data = {
            'relation': {},
        }
        if req.method == 'POST':
            # for modifying the relations TICKET_MODIFY is required for
            # both the source and the destination tickets
            req.perm.require('TICKET_MODIFY')

            if 'remove' in req.args:
                rellist = req.args.get('sel')
                if rellist:
                    if isinstance(rellist, basestring):
                        rellist = [rellist, ]
                    self.remove_relations(req, rellist)
            elif 'add' in req.args:
                relation = dict(
                    destination=req.args.get('dest_tid', ''),
                    type=req.args.get('reltype', ''),
                    comment=req.args.get('comment', ''),
                )
                try:
                    trs = TicketRelationsSpecifics(self.env)
                    dest_ticket = trs.find_ticket(relation['destination'])
                except NoSuchTicketError:
                    data['error'] = _('Invalid ticket ID.')
                else:
                    req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id))

                    try:
                        relsys.add(ticket, dest_ticket,
                            relation['type'],
                            relation['comment'],
                            req.authname)
                    except NoSuchTicketError:
                        data['error'] = _('Invalid ticket ID.')
                    except UnknownRelationType:
                        data['error'] = _('Unknown relation type.')
                    except ValidationError as ex:
                        data['error'] = ex.message

                if 'error' in data:
                    data['relation'] = relation
            else:
                raise TracError(_('Invalid operation.'))

        data.update({
            'ticket': ticket,
            'reltypes': sorted(relsys.get_relation_types().iteritems(),
                key=lambda x: x[0]),
            'relations': self.get_ticket_relations(ticket),
        })
        return 'relations_manage.html', data, None
Пример #22
0
    def process_request(self, req):
        tid = req.args.get('id')
        if not tid:
            raise TracError(_('No ticket id provided.'))

        try:
            ticket = Ticket(self.env, tid)
        except ValueError:
            raise TracError(_('Invalid ticket id.'))

        req.perm.require('TICKET_VIEW')
        relsys = RelationsSystem(self.env)

        data = {
            'relation': {},
        }
        if req.method == 'POST':
            # for modifying the relations TICKET_MODIFY is required for
            # both the source and the destination tickets
            req.perm.require('TICKET_MODIFY')

            if 'remove' in req.args:
                rellist = req.args.get('sel')
                if rellist:
                    if isinstance(rellist, basestring):
                        rellist = [
                            rellist,
                        ]
                    self.remove_relations(req, rellist)
            elif 'add' in req.args:
                relation = dict(
                    destination=req.args.get('dest_tid', ''),
                    type=req.args.get('reltype', ''),
                    comment=req.args.get('comment', ''),
                )
                try:
                    trs = TicketRelationsSpecifics(self.env)
                    dest_ticket = trs.find_ticket(relation['destination'])
                except NoSuchTicketError:
                    data['error'] = _('Invalid ticket ID.')
                else:
                    req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id))

                    try:
                        relsys.add(ticket, dest_ticket, relation['type'],
                                   relation['comment'], req.authname)
                    except NoSuchTicketError:
                        data['error'] = _('Invalid ticket ID.')
                    except UnknownRelationType:
                        data['error'] = _('Unknown relation type.')
                    except ValidationError as ex:
                        data['error'] = ex.message

                if 'error' in data:
                    data['relation'] = relation
            else:
                raise TracError(_('Invalid operation.'))

        data.update({
            'ticket':
            ticket,
            'reltypes':
            sorted(relsys.get_relation_types().iteritems(),
                   key=lambda x: x[0]),
            'relations':
            self.get_ticket_relations(ticket),
        })
        return 'relations_manage.html', data, None
Пример #23
0
 def render_relation_type(self, end):
     return RelationsSystem(self.env)._labels[end]
Пример #24
0
    def process_request(self, req):
        tid = req.args.get('id')
        if not tid:
            raise TracError(_('No ticket id provided.'))

        try:
            ticket = Ticket(self.env, tid)
        except ValueError:
            raise TracError(_('Invalid ticket id.'))

        # For access to the relation management, TICKET_MODIFY is required.
        req.perm.require('TICKET_MODIFY')
        relsys = RelationsSystem(self.env)

        data = {
            'relation': {},
        }
        if req.method == 'POST':
            # for modifying the relations TICKET_MODIFY is required for
            # both the source and the destination tickets

            if 'remove' in req.args:
                rellist = req.args.get('sel')
                if rellist:
                    if isinstance(rellist, basestring):
                        rellist = [
                            rellist,
                        ]
                    self.remove_relations(req, rellist)
            elif 'add' in req.args:
                relation = dict(
                    destination=req.args.get('dest_tid', ''),
                    type=req.args.get('reltype', ''),
                    comment=req.args.get('comment', ''),
                )
                try:
                    trs = TicketRelationsSpecifics(self.env)
                    dest_ticket = trs.find_ticket(relation['destination'])
                except NoSuchTicketError:
                    data['error'] = _('Invalid ticket ID.')
                else:
                    req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id))

                    try:
                        dbrel = relsys.add(ticket, dest_ticket,
                                           relation['type'],
                                           relation['comment'], req.authname)
                    except NoSuchTicketError:
                        data['error'] = _('Invalid ticket ID.')
                    except UnknownRelationType:
                        data['error'] = _('Unknown relation type.')
                    except ValidationError as ex:
                        data['error'] = ex.message
                    else:
                        # Notify
                        try:
                            self.notify_relation_changed(dbrel)
                        except Exception, e:
                            self.log.error(
                                "Failure sending notification on"
                                "creation of relation: %s",
                                exception_to_unicode(e))
                            add_warning(
                                req,
                                _(
                                    "The relation has been added, "
                                    "but an error occurred while "
                                    "sending notifications: "
                                    "%(message)s",
                                    message=to_unicode(e)))

                if 'error' in data:
                    data['relation'] = relation
            else:
                raise TracError(_('Invalid operation.'))