Beispiel #1
0
 def detail_view(self, req, cat, page, link):
     links_configuration = LinksConfiguration(self.env)
     (source, target) = links_configuration.extract_types(link)
     copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.COPY),
                                                      default='').split(',')]
     show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.SHOW),
                                                      default='').split(',')]
     ticket_system = AgiloTicketSystem(self.env)
     # dict of name->label for all core and custom fields
     labels = dict([(f['name'], f['label'])
                    for f in ticket_system.get_ticket_fields()])
     cascade_delete = source + '-' + target in self._get_delete_pairs()
     data = {
         'view': 'detail',
         'link': link,
         'source': source,
         'target': target,
         'source_fields': self.config.TYPES[source],
         'target_fields': self.config.TYPES[target],
         'labels': labels,
         'copy_fields': copy_fields,
         'show_fields': show_fields,
         'cascade_delete': cascade_delete
     }
     return 'agilo_admin_links.html', data
Beispiel #2
0
    def detail_save_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        fields = req.args.get('copy_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set copy options for this link
        self.links.change_option('%s.%s.%s' % (source, target, LinkOption.COPY),
                                 ', '.join(fields))
        
        fields = req.args.get('show_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set show options for this link
        self.links.change_option('%s.%s.%s' % (source, target, LinkOption.SHOW),
                                 ', '.join(fields))
        
        cascade_delete = req.args.get('cascade_delete')
        delete_pairs = self._get_delete_pairs()
        if cascade_delete and source+'-'+target not in delete_pairs:
            delete_pairs[source+'-'+target] = (source, target)
            self.links.change_option(LinkOption.DELETE, 
                                     ', '.join(delete_pairs.keys()))

        elif not cascade_delete and source+'-'+target in self._get_delete_pairs():
            del delete_pairs[source+'-'+target]
            self.links.change_option(LinkOption.DELETE, 
                                     ', '.join(delete_pairs.keys()))
            
        
        # saved it, redirect back to admin view
        self.links.save()
        req.redirect(req.href.admin(cat, page))
Beispiel #3
0
 def detail_view(self, req, cat, page, link):
     links_configuration = LinksConfiguration(self.env)
     (source, target) = links_configuration.extract_types(link)
     copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.COPY), 
                                                      default='').split(',')]
     show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.SHOW), 
                                                      default='').split(',')]
     ticket_system = AgiloTicketSystem(self.env)
     # dict of name->label for all core and custom fields
     labels = dict([(f['name'], f['label']) for f in ticket_system.get_ticket_fields()])
     cascade_delete = source+'-'+target in self._get_delete_pairs()
     data = {
         'view': 'detail',
         'link': link,
         'source' : source,
         'target' : target,
         'source_fields' : self.config.TYPES[source],
         'target_fields' : self.config.TYPES[target],
         'labels' : labels,
         'copy_fields' : copy_fields,
         'show_fields' : show_fields,
         'cascade_delete': cascade_delete
     }
     return 'agilo_admin_links.html', data
Beispiel #4
0
    def detail_save_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        fields = req.args.get('copy_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set copy options for this link
        self.links.change_option(
            '%s.%s.%s' % (source, target, LinkOption.COPY), ', '.join(fields))

        fields = req.args.get('show_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set show options for this link
        self.links.change_option(
            '%s.%s.%s' % (source, target, LinkOption.SHOW), ', '.join(fields))

        cascade_delete = req.args.get('cascade_delete')
        delete_pairs = self._get_delete_pairs()
        if cascade_delete and source + '-' + target not in delete_pairs:
            delete_pairs[source + '-' + target] = (source, target)
            self.links.change_option(LinkOption.DELETE,
                                     ', '.join(delete_pairs.keys()))

        elif not cascade_delete and source + '-' + target in self._get_delete_pairs(
        ):
            del delete_pairs[source + '-' + target]
            self.links.change_option(LinkOption.DELETE,
                                     ', '.join(delete_pairs.keys()))

        # saved it, redirect back to admin view
        self.links.save()
        req.redirect(req.href.admin(cat, page))
 def test_missing_agilo_links_allow(self):
     """Tests robustness of config in case the 'allow' parameter is missing"""
     env = self.teh.get_env()
     env.config.remove('agilo-links', 'allow')
     lc = LinksConfiguration(env)
     # Force initialization
     lc._initialized = False
     lc.initialize()
Beispiel #6
0
 def test_config_reloads_links_configuration_on_change(self):
     self.assert_contains(
         'story',
         LinksConfiguration(
             self.env).get_allowed_destination_types('requirement'))
     self.config.change_option('allow',
                               '',
                               section=AgiloConfig.AGILO_LINKS,
                               save=True)
     self.assert_not_contains(
         'story',
         LinksConfiguration(
             self.env).get_allowed_destination_types('requirement'))
Beispiel #7
0
    def get_tickets_matching(self, t_id, summary):
        """
        Returns a list of dictionaries (id: value, summary: value) matching the summary 
        request and excluding the requesting ticket having id = id.
        """
        try:
            t_id = int(t_id)  # Make sure it is an int :-)
            keyword = re.compile(summary, re.IGNORECASE)
            db = self.env.get_db_cnx()

            from agilo.ticket.model import AgiloTicketModelManager
            sql = """SELECT id, type, summary FROM ticket WHERE id != $id $allowed 
                  AND id NOT IN (SELECT dest FROM %s WHERE src = $id UNION
                  SELECT src FROM %s WHERE dest = $id) ORDER BY summary""" \
                    % (LINKS_TABLE, LINKS_TABLE)
            sql_query = string.Template(sql)
            sql_allowed = "AND ticket.type IN ('%s')"
            t_type = AgiloTicketModelManager(
                self.env).get(tkt_id=t_id).get_type()
            linkconfig = LinksConfiguration(self.env)
            if linkconfig.is_allowed_source_type(t_type):
                allowed_types = linkconfig.get_allowed_destination_types(
                    t_type)
                allowed = sql_allowed % '\', \''.join(allowed_types)
            else:
                debug(self, "No Key found for #%s#" % repr(t_type))
                allowed = ''

            sql_query = sql_query.substitute({'id': t_id, 'allowed': allowed})
            debug(self, "SQL: %s" % sql_query)
            cursor = db.cursor()
            cursor.execute(sql_query)

            results = []
            for row in cursor:
                if keyword.search(row[2] or ''):
                    results.append({
                        'id': row[0],
                        'type': row[1],
                        'summary': row[2]
                    })

            debug(self, "Search Results: %s" % str(results))
            return results

        except Exception, e:
            warning(self, e)
            msg = "[%s]: ERROR: Search module unable to complete query!" % \
                    self.__class__.__name__
            raise TracError(msg)
Beispiel #8
0
 def get_tickets_matching(self, t_id, summary):
     """
     Returns a list of dictionaries (id: value, summary: value) matching the summary 
     request and excluding the requesting ticket having id = id.
     """
     try:
         t_id = int(t_id) # Make sure it is an int :-)
         keyword = re.compile(summary, re.IGNORECASE)
         db = self.env.get_db_cnx()
         
         from agilo.ticket.model import AgiloTicketModelManager
         sql = """SELECT id, type, summary FROM ticket WHERE id != $id $allowed 
               AND id NOT IN (SELECT dest FROM %s WHERE src = $id UNION
               SELECT src FROM %s WHERE dest = $id) ORDER BY summary""" \
                 % (LINKS_TABLE, LINKS_TABLE)
         sql_query = string.Template(sql)
         sql_allowed = "AND ticket.type IN ('%s')"
         t_type = AgiloTicketModelManager(self.env).get(tkt_id=t_id).get_type()
         linkconfig = LinksConfiguration(self.env)
         if linkconfig.is_allowed_source_type(t_type):
             allowed_types = linkconfig.get_allowed_destination_types(t_type)
             allowed = sql_allowed % '\', \''.join(allowed_types)
         else:
             debug(self, "No Key found for #%s#" % repr(t_type))
             allowed = ''
                 
         sql_query = sql_query.substitute({'id' : t_id, 'allowed' : allowed})
         debug(self, "SQL: %s" % sql_query)
         cursor = db.cursor()
         cursor.execute(sql_query)
         
         results = []
         for row in cursor:
             if keyword.search(row[2] or ''):
                 results.append({'id': row[0], 'type': row[1], 
                                 'summary': row[2]})  
         
         debug(self, "Search Results: %s" % str(results))
         return results
         
     except Exception, e:
         warning(self, e)
         msg = "[%s]: ERROR: Search module unable to complete query!" % \
                 self.__class__.__name__
         raise TracError(msg) 
    def test_handles_types_with_dashes(self):
        from_type = 'with-dashes'
        to_type = 'bug'
        custom_type = TicketType(self.env)
        custom_type.name = from_type
        custom_type.insert()

        config = AgiloConfig(self.env)
        config.change_option(from_type, "", section=AgiloConfig.AGILO_TYPES)
        config.reload()
        self.assert_true(from_type in config.get_available_types())

        section = config.get_section(AgiloConfig.AGILO_LINKS)
        allowed_links = section.get_list('allow')
        allowed_links.append('%s-%s' % (from_type, to_type))
        section.change_option('allow', ', '.join(allowed_links), save=True)
        self.links_configuration = LinksConfiguration(self.env)
        self.assert_equals(self.links_configuration.get_alloweds(from_type)[0].dest_type, to_type)
Beispiel #10
0
    def _check_if_user_can_create_referenced_tickets(self, req, data):
        if 'ticket' not in data:
            data['can_create_at_least_one_referenced_type'] = False
            return

        ticket = data['ticket']
        ticket_type = ticket[Key.TYPE]

        can_create_at_least_one_referenced_type = False
        for allowed_type in LinksConfiguration(
                self.env).get_allowed_destination_types(ticket_type):
            permission_name = CoreTemplateProvider(
                self.env).get_permission_name_to_create(allowed_type)
            if permission_name in req.perm:
                can_create_at_least_one_referenced_type = True
                break
        data[
            'can_create_at_least_one_referenced_type'] = can_create_at_least_one_referenced_type
class LinksConfigurationCachingTest(AgiloTestCase):
    def setUp(self):
        self.super()
        self.links_configuration = LinksConfiguration(self.env)
    
    def test_initializes_at_init(self):
        self.assert_true(self.links_configuration.is_initialized())

    def test_handles_types_with_dashes(self):
        from_type = 'with-dashes'
        to_type = 'bug'
        custom_type = TicketType(self.env)
        custom_type.name = from_type
        custom_type.insert()

        config = AgiloConfig(self.env)
        config.change_option(from_type, "", section=AgiloConfig.AGILO_TYPES)
        config.reload()
        self.assert_true(from_type in config.get_available_types())

        section = config.get_section(AgiloConfig.AGILO_LINKS)
        allowed_links = section.get_list('allow')
        allowed_links.append('%s-%s' % (from_type, to_type))
        section.change_option('allow', ', '.join(allowed_links), save=True)
        self.links_configuration = LinksConfiguration(self.env)
        self.assert_equals(self.links_configuration.get_alloweds(from_type)[0].dest_type, to_type)

    def _requirement_links(self):
        return self.links_configuration.get_allowed_destination_types('requirement')
    
    def test_invalidating_the_cache_reloads_allowed_links_configuration(self):
        AgiloConfig(self.env).change_option('allow', 'requirement-task', section='agilo-links', save=True)
        self.links_configuration.reinitialize()
        self.assert_not_contains('story', self._requirement_links())
        self.assert_contains('task', self._requirement_links())

    def _bug_calculated_properties(self):
        return AgiloTicketSystem(self.env).get_agilo_properties('bug')[0].keys()

    def test_invalidating_the_cache_reloads_calculated_properties(self):
        self.assert_contains('total_remaining_time', self._bug_calculated_properties())
        AgiloConfig(self.env).change_option('bug.calculate', '', section='agilo-links', save=True)
        self.links_configuration.reinitialize()
        self.assert_not_contains('total_remaining_time', self._bug_calculated_properties())
Beispiel #12
0
 def _get_allowed_links(self):
     """Returns the dictionary containing the allowed links pairs"""
     links_configuration = LinksConfiguration(self.env)
     return dict([(l, list(links_configuration.extract_types(l))) for l in self.links.get_list(LinkOption.ALLOW)])
 def setUp(self):
     self.super()
     self.links_configuration = LinksConfiguration(self.env)
 def _reset_links_configuration(self):
     # Reinitialize the link configuration
     lc = LinksConfiguration(self.teh.env)
     lc._initialized = False
     lc.initialize()
Beispiel #15
0
 def _get_allowed_links(self):
     """Returns the dictionary containing the allowed links pairs"""
     links_configuration = LinksConfiguration(self.env)
     return dict([(l, list(links_configuration.extract_types(l)))
                  for l in self.links.get_list(LinkOption.ALLOW)])
Beispiel #16
0
 def _get_delete_pairs(self):
     """Returns the dictionary containing the cascade delete pairs"""
     links_configuration = LinksConfiguration(self.env)
     return dict([(l, list(links_configuration.extract_types(l)))
                  for l in self.links.get_list(LinkOption.DELETE)])
Beispiel #17
0
 def can_create_at_least_one_referenced_type(ticket_type):
     for allowed_type in LinksConfiguration(self.env).get_allowed_destination_types(ticket_type):
         permission_name = CoreTemplateProvider(self.env).get_permission_name_to_create(allowed_type)
         if permission_name in perm:
             return True
     return False
Beispiel #18
0
 def _get_delete_pairs(self):
     """Returns the dictionary containing the cascade delete pairs"""
     links_configuration = LinksConfiguration(self.env)
     return dict([(l, list(links_configuration.extract_types(l))) for l in self.links.get_list(LinkOption.DELETE)])