Exemplo n.º 1
0
    def test_delete(self):
        """test that we are able to delete Products"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        post = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(0, len(post))
Exemplo n.º 2
0
    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {'prefix':'tp2',
                   'name':'test project 2',
                   'description':'a different test project'}
        p3_data = {'prefix':'tp3',
                   'name':'test project 3',
                   'description':'test project'}

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'prefix':'tp3', 'name':'test project 3'}))
        self.assertEqual(1, len(products))
Exemplo n.º 3
0
    def _do_save(self, req, product):
        """common processing for product save events"""
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        prefix = req.args.get('prefix')
        description = req.args.get('description', '')

        owner = req.args.get('owner') or req.authname
        keys = {'prefix': prefix}
        field_data = {'name': name,
                      'description': description,
                      'owner': owner,
                      }

        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        if product._exists:
            if name != product.name and Product.select(self.env,
                                                       where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))
            elif not name:
                warn(_('You must provide a name for the product.'))
            else:
                req.perm.require('PRODUCT_MODIFY')
                product.update_field_dict(field_data)
                product.update(req.authname)
                add_notice(req, _('Your changes have been saved.'))
        else:
            req.perm.require('PRODUCT_CREATE')

            if not prefix:
                warn(_('You must provide a prefix for the product.'))
            elif Product.select(self.env, where={'prefix': prefix}):
                warn(_('Product "%(id)s" already exists, please choose another '
                       'prefix.', id=prefix))
            if not name:
                warn(_('You must provide a name for the product.'))
            elif Product.select(self.env, where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))

            if not warnings:
                prod = Product(self.env)
                prod.update_field_dict(keys)
                prod.update_field_dict(field_data)
                prod.insert()
                add_notice(req, _('The product "%(id)s" has been added.',
                                  id=prefix))

        if warnings:
            product.update_field_dict(keys)
            product.update_field_dict(field_data)
            return self._render_editor(req, product)
        req.redirect(req.href.products(prefix))
Exemplo n.º 4
0
    def test_update(self):
        """tests that we can use update to push data to the database"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('test project', product._data['name'])

        new_data = {'prefix':'tp',
                    'name':'updated',
                    'description':'nothing'}
        product._data.update(new_data)
        product.update()

        comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('updated', comp_product._data['name'])
Exemplo n.º 5
0
    def lookup_env(cls, env, prefix=None, name=None):
        """Instantiate environment according to product prefix or name

        @throws LookupError if no product matches neither prefix nor name
        """
        if isinstance(env, ProductEnvironment):
            global_env = env.parent
        else:
            global_env = env

        # FIXME: Update if multiproduct.dbcursor.GLOBAL_PRODUCT != ''
        if not prefix and not name:
            return global_env
        elif isinstance(env, ProductEnvironment) and \
                env.product.prefix == prefix:
            return env
        if prefix:
            try:
                return ProductEnvironment(global_env, prefix)
            except LookupError:
                if not name:
                    raise
        if name:
            # Lookup product by name
            products = Product.select(global_env, where={'name' : name})
            if products:
                return ProductEnvironment(global_env, products[0])
            else:
                raise LookupError("Missing product '%s'" % (name,))
        else:
            raise LookupError("Mising product '%s'" % (prefix or name,))
Exemplo n.º 6
0
    def find_ticket(self, ticket_spec):
        ticket = None
        m = re.match(r'#?(?P<tid>\d+)', ticket_spec)
        if m:
            tid = m.group('tid')
            try:
                ticket = Ticket(self.env, tid)
            except ResourceNotFound:
                # ticket not found in current product, try all other products
                for p in Product.select(self.env):
                    if p.prefix != self.env.product.prefix:
                        # TODO: check for PRODUCT_VIEW permissions
                        penv = ProductEnvironment(self.env.parent, p.prefix)
                        try:
                            ticket = Ticket(penv, tid)
                        except ResourceNotFound:
                            pass
                        else:
                            break

        # ticket still not found, use fallback for <prefix>:ticket:<id> syntax
        if ticket is None:
            try:
                resource = ResourceIdSerializer.get_resource_by_id(ticket_spec)
                ticket = self._create_ticket_by_full_id(resource)
            except:
                raise NoSuchTicketError
        return ticket
Exemplo n.º 7
0
 def test_update_key_change(self):
     """tests that we raise an error for attempting to update key fields"""
     bad_data = {'prefix':'tp0',
                 'name':'update',
                 'description':'nothing'}
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     product._data.update(bad_data)
     self.assertRaises(TracError, product.update)
Exemplo n.º 8
0
 def _render_list(self, req):
     """products list"""
     products = [p for p in Product.select(self.env)
                 if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                            p.prefix))]
     data = {'products': products,
             'context': web_context(req, Resource('product', None))}
     return 'product_list.html', data, None
Exemplo n.º 9
0
    def test_field_set(self):
        """tests that we can use table.field = something to set field data"""
        prefix = self.default_data['prefix']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]

        new_description = 'test change of description'
        product.description = new_description
        self.assertEqual(new_description, product.description)
Exemplo n.º 10
0
 def test_field_data_get(self):
     """tests that we can use table.field syntax to get to the field data"""
     prefix = self.default_data['prefix']
     name = self.default_data['name']
     description = self.default_data['description']
     product = list(Product.select(self.env, where={'prefix': prefix}))[0]
     self.assertEqual(prefix, product.prefix)
     self.assertEqual(name, product.name)
     self.assertEqual(description, product.description)
Exemplo n.º 11
0
 def test_field_data_get(self):
     """tests that we can use table.field syntax to get to the field data"""
     prefix = self.default_data['prefix']
     name = self.default_data['name']
     description = self.default_data['description']
     product = list(Product.select(self.env, where={'prefix':prefix}))[0]
     self.assertEqual(prefix, product.prefix)
     self.assertEqual(name, product.name)
     self.assertEqual(description, product.description)
Exemplo n.º 12
0
 def _render_list(self, req):
     """products list"""
     products = [p for p in Product.select(self.env)
                 if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                            p.prefix))]
     map(lambda p: setattr(p, 'href', resolve_product_href(
         lookup_product_env(self.env, p.prefix), self.env)), products)
     data = {'products': products,
             'context': web_context(req, Resource('product', None))}
     return 'product_list.html', data, None
Exemplo n.º 13
0
 def test_update_key_change(self):
     """tests that we raise an error for attempting to update key fields"""
     bad_data = {
         'prefix': 'tp0',
         'name': 'update',
         'description': 'nothing'
     }
     product = list(Product.select(self.env, where={'prefix': 'tp'}))[0]
     product._data.update(bad_data)
     self.assertRaises(TracError, product.update)
Exemplo n.º 14
0
    def test_migrating_to_multiproduct_with_custom_default_prefix(self):
        ticket = self.insert_ticket('ticket')

        self.env.config.set('multiproduct', 'default_product_prefix', 'xxx')
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)
        self.assertEqual(products[0].prefix, 'xxx')
Exemplo n.º 15
0
    def test_migrating_to_multiproduct_with_custom_default_prefix(self):
        ticket = self.insert_ticket('ticket')

        self.env.config.set('multiproduct', 'default_product_prefix', 'xxx')
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)
        self.assertEqual(products[0].prefix, 'xxx')
Exemplo n.º 16
0
 def _render_list(self, req):
     """products list"""
     products = [
         p for p in Product.select(self.env)
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product', p.prefix))
     ]
     data = {
         'products': products,
         'context': web_context(req, Resource('product', None))
     }
     return 'product_list.html', data, None
Exemplo n.º 17
0
    def test_insert(self):
        """test saving new Product"""
        data = {'prefix':'new', 'name':'new', 'description':'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))
Exemplo n.º 18
0
 def test_insert(self):
     """test saving new Product"""
     data = {'prefix':'new', 'name':'new', 'description':'new'}
     product = Product(self.env)
     product._data.update(data)
     product.insert()
     
     check_products = list(Product.select(self.env, where={'prefix':'new'}))
     
     self.assertEqual(product._data['prefix'],
                      check_products[0]._data['prefix'])
     self.assertEqual(1, len(check_products))
Exemplo n.º 19
0
 def get_product_list(cls, env, req, href_fcn=None):
     """Returns a list of products as (prefix, name, url) tuples
     """
     if href_fcn is None:
         href_fcn = req.href.products
     product_list = []
     for product in Product.select(env):
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                    product.prefix).
                                       child(product.resource)):
             product_list.append((product.prefix, product.name,
                                  href_fcn(product.prefix)))
     return product_list
Exemplo n.º 20
0
 def get_product_list(cls, env, req, href_fcn=None):
     """Returns a list of products as (prefix, name, url) tuples
     """
     if href_fcn is None:
         href_fcn = req.href.products
     product_list = []
     for product in Product.select(env):
         if 'PRODUCT_VIEW' in req.perm(
                 Neighborhood('product',
                              product.prefix).child(product.resource)):
             product_list.append(
                 (product.prefix, product.name, href_fcn(product.prefix)))
     return product_list
Exemplo n.º 21
0
 def _render_list(self, req):
     """products list"""
     products = [
         p for p in Product.select(self.env)
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product', p.prefix))
     ]
     map(
         lambda p: setattr(
             p, 'href',
             resolve_product_href(lookup_product_env(self.env, p.prefix),
                                  self.env)), products)
     data = {
         'products': products,
         'context': web_context(req, Resource('product', None))
     }
     return 'product_list.html', data, None
Exemplo n.º 22
0
    def pre_process_request(self, req, handler):
        """pre process request filter"""
        pid = None
        match = PRODUCT_RE.match(req.path_info)
        if match:
            dispatcher = self.env[RequestDispatcher]
            if dispatcher is None:
                raise TracError('Unable to load RequestDispatcher.')
            pid = match.group('pid')

        if pid:
            products = Product.select(self.env, where={'prefix': pid})
            if pid and len(products) == 1:
                req.args['productid'] = pid
                req.args['product'] = products[0].name
                if handler is self and match.group('pathinfo') not in ('',
                                                                       '/'):
                    # select a new handler
                    environ = req.environ.copy()
                    pathinfo = environ['PATH_INFO'].split('/')
                    pathinfo = '/'.join(pathinfo[:1] + pathinfo[3:])
                    environ['PATH_INFO'] = pathinfo
                    newreq = Request(environ, lambda *args, **kwds: None)

                    new_handler = None
                    for hndlr in dispatcher.handlers:
                        if hndlr is not self and hndlr.match_request(newreq):
                            new_handler = hndlr
                            req.args.update(newreq.args)
                            break
                    if new_handler is None:
                        if req.path_info.endswith('/'):
                            target = req.path_info.rstrip('/').encode('utf-8')
                            if req.query_string:
                                target += '?' + req.query_string
                            req.redirect(req.href + target, permanent=True)
                        raise HTTPNotFound('No handler matched request to %s',
                                           req.path_info)
                    handler = new_handler
            else:
                raise ResourceNotFound(
                    _("Product %(id)s does not exist.", id=pid),
                    _("Invalid product id"))

        return handler
Exemplo n.º 23
0
 def pre_process_request(self, req, handler):
     """pre process request filter"""
     pid = None
     match = PRODUCT_RE.match(req.path_info)
     if match:
         dispatcher = self.env[RequestDispatcher]
         if dispatcher is None:
             raise TracError('Unable to load RequestDispatcher.')
         pid = match.group('pid')
     
     if pid:
         products = Product.select(self.env, where={'prefix': pid})
         if pid and len(products) == 1:
             req.args['productid'] = pid
             req.args['product'] = products[0].name
             if handler is self and match.group('pathinfo') not in ('', '/'):
                 # select a new handler
                 environ = req.environ.copy()
                 pathinfo = environ['PATH_INFO'].split('/')
                 pathinfo = '/'.join(pathinfo[:1] + pathinfo[3:])
                 environ['PATH_INFO'] = pathinfo
                 newreq = Request(environ, lambda *args, **kwds: None)
                 
                 new_handler = None
                 for hndlr in dispatcher.handlers:
                     if hndlr is not self and hndlr.match_request(newreq):
                         new_handler = hndlr
                         req.args.update(newreq.args)
                         break
                 if new_handler is None:
                     if req.path_info.endswith('/'):
                         target = req.path_info.rstrip('/').encode('utf-8')
                         if req.query_string:
                             target += '?' + req.query_string
                         req.redirect(req.href + target, permanent=True)
                     raise HTTPNotFound('No handler matched request to %s',
                                        req.path_info)
                 handler = new_handler
         else:
             raise ResourceNotFound(_("Product %(id)s does not exist.", 
                                      id=pid), _("Invalid product id"))
     
     return handler
Exemplo n.º 24
0
    def process_request(self, req):
        """Override for TicketModule process_request"""
        ticketid = req.args.get('id')
        productid = req.args.get('productid', '')

        if not ticketid:
            # if /newticket is executed in global scope (from QCT), redirect
            # the request to /products/<first_product_in_DB>/newticket
            if not productid and \
                    not isinstance(self.env, ProductEnvironment):
                default_product = self.env.config.get('ticket',
                                                      'default_product')
                products = Product.select(self.env, {'fields': ['prefix']})
                prefixes = [prod.prefix for prod in products]
                if not default_product or default_product not in prefixes:
                    default_product = products[0].prefix
                req.redirect(req.href.products(default_product, 'newticket'))

            return self._process_newticket_request(req)

        if req.path_info in ('/newticket', '/products'):
            raise TracError(_("id can't be set for a new ticket request."))

        if isinstance(self.env, ProductEnvironment):
            ticket = Ticket(self.env, ticketid)
            if productid and ticket['product'] != productid:
                msg = "Ticket %(id)s in product '%(prod)s' does not exist."
                raise ResourceNotFound(_(msg, id=ticketid, prod=productid),
                                       _("Invalid ticket number"))
            return self._process_ticket_request(req)

        # executed in global scope -> assume ticketid=UID, redirect to product
        with self.env.db_direct_query as db:
            rows = db("""SELECT id,product FROM ticket WHERE uid=%s""",
                      (ticketid,))
            if not rows:
                msg = "Ticket with uid %(uid)s does not exist."
                raise ResourceNotFound(_(msg, uid=ticketid),
                                       _("Invalid ticket number"))
            tid, prefix = rows[0]
            req.redirect(req.href.products(prefix, 'ticket', tid))
Exemplo n.º 25
0
    def process_request(self, req):
        """Override for TicketModule process_request"""
        ticketid = req.args.get('id')
        productid = req.args.get('productid', '')

        if not ticketid:
            # if /newticket is executed in global scope (from QCT), redirect
            # the request to /products/<first_product_in_DB>/newticket
            if not productid and \
                    not isinstance(self.env, ProductEnvironment):
                default_product = self.env.config.get('ticket',
                                                      'default_product')
                products = Product.select(self.env, {'fields': ['prefix']})
                prefixes = [prod.prefix for prod in products]
                if not default_product or default_product not in prefixes:
                    default_product = products[0].prefix
                req.redirect(req.href.products(default_product, 'newticket'))

            return self._process_newticket_request(req)

        if req.path_info in ('/newticket', '/products'):
            raise TracError(_("id can't be set for a new ticket request."))

        if isinstance(self.env, ProductEnvironment):
            ticket = Ticket(self.env, ticketid)
            if productid and ticket['product'] != productid:
                msg = "Ticket %(id)s in product '%(prod)s' does not exist."
                raise ResourceNotFound(_(msg, id=ticketid, prod=productid),
                                       _("Invalid ticket number"))
            return self._process_ticket_request(req)

        # executed in global scope -> assume ticketid=UID, redirect to product
        with self.env.db_direct_query as db:
            rows = db("""SELECT id,product FROM ticket WHERE uid=%s""",
                      (ticketid, ))
            if not rows:
                msg = "Ticket with uid %(uid)s does not exist."
                raise ResourceNotFound(_(msg, uid=ticketid),
                                       _("Invalid ticket number"))
            tid, prefix = rows[0]
            req.redirect(req.href.products(prefix, 'ticket', tid))
Exemplo n.º 26
0
    def _render_link(self, context, name, label, extra='', prefix=None):
        """Render link to product page.
        """
        product_env = product = None
        env = self.env
        if isinstance(env, ProductEnvironment):
            if (prefix is not None and env.product.prefix == prefix) \
                    or (prefix is None and env.name == name):
                product_env = env
            env = env.parent
        try:
            if product_env is None:
                if prefix is not None:
                    product_env = ProductEnvironment(env, to_unicode(prefix))
                else:
                    product = Product.select(env,
                                             where={'name' : to_unicode(name)})
                    if not product:
                        raise LookupError("Missing product")
                    product_env = ProductEnvironment(env,
                                                     to_unicode(product[0]))
        except LookupError:
            pass

        if product_env is not None:
            product = product_env.product
            href = resolve_product_href(to_env=product_env, at_env=self.env)
            if 'PRODUCT_VIEW' in context.perm(product.resource):
                return tag.a(label, class_='product', href=href() + extra,
                             title=product.name)
        if 'PRODUCT_CREATE' in context.perm('product', name):
            params = [('action', 'new')]
            if prefix:
                params.append( ('prefix', prefix) )
            if name:
                params.append( ('name', name) )
            return tag.a(label, class_='missing product',
                    href=env.href('products', params),
                    rel='nofollow')
        return tag.a(label, class_='missing product')
Exemplo n.º 27
0
    def __init__(self, env, product, create=False):
        """Initialize the product environment.

        :param env:     the global Trac environment
        :param product: product prefix or an instance of
                        multiproduct.model.Product
        """
        if not isinstance(env, trac.env.Environment):
            cls = self.__class__
            raise TypeError("Initializer must be called with " \
                "trac.env.Environment instance as first argument " \
                "(got %s instance instead)" %
                         (cls.__module__ + '.' + cls.__name__, ))

        ComponentManager.__init__(self)

        if isinstance(product, Product):
            if product._env is not env:
                raise ValueError("Product's environment mismatch")
        elif isinstance(product, basestring):
            products = Product.select(env, where={'prefix': product})
            if len(products) == 1 :
                product = products[0]
            else:
                env.log.debug("Products for '%s' : %s",
                              product, products)
                raise LookupError("Missing product %s" % (product,))

        self.parent = env
        self.product = product
        self.systeminfo = []

        self.setup_config()

        # when creating product environment, invoke `IEnvironmentSetupParticipant.environment_created`
        # for all setup participants that don't support multi product environments
        if create:
            for participant in self.product_setup_participants:
                with ComponentEnvironmentContext(self, participant):
                    participant.environment_created()
Exemplo n.º 28
0
    def _render_link(self, context, name, label, extra='', prefix=None):
        """Render link to product page.
        """
        product_env = product = None
        env = self.env
        if isinstance(env, ProductEnvironment):
            if (prefix is not None and env.product.prefix == prefix) \
                    or (prefix is None and env.name == name):
                product_env = env
            env = env.parent
        try:
            if product_env is None:
                if prefix is not None:
                    product_env = ProductEnvironment(env, to_unicode(prefix))
                else:
                    product = Product.select(env,
                                             where={'name' : to_unicode(name)})
                    if not product:
                        raise LookupError("Missing product")
                    product_env = ProductEnvironment(env,
                                                     to_unicode(product[0]))
        except LookupError:
            pass

        if product_env is not None:
            product = product_env.product
            href = resolve_product_href(to_env=product_env, at_env=self.env)
            if 'PRODUCT_VIEW' in context.perm(product.resource):
                return tag.a(label, class_='product', href=href() + extra,
                             title=product.name)
        if 'PRODUCT_CREATE' in context.perm('product', name):
            params = [('action', 'new')]
            if prefix:
                params.append( ('prefix', prefix) )
            if name:
                params.append( ('name', name) )
            return tag.a(label, class_='missing product',
                    href=env.href('products', params),
                    rel='nofollow')
        return tag.a(label, class_='missing product')
Exemplo n.º 29
0
    def __init__(self, env, product, create=False):
        """Initialize the product environment.

        :param env:     the global Trac environment
        :param product: product prefix or an instance of
                        multiproduct.model.Product
        """
        if not isinstance(env, trac.env.Environment):
            cls = self.__class__
            raise TypeError("Initializer must be called with " \
                "trac.env.Environment instance as first argument " \
                "(got %s instance instead)" %
                         (cls.__module__ + '.' + cls.__name__, ))

        ComponentManager.__init__(self)

        if isinstance(product, Product):
            if product._env is not env:
                raise ValueError("Product's environment mismatch")
        elif isinstance(product, basestring):
            products = Product.select(env, where={'prefix': product})
            if len(products) == 1:
                product = products[0]
            else:
                env.log.debug("Products for '%s' : %s", product, products)
                raise LookupError("Missing product %s" % (product, ))

        self.parent = env
        self.product = product
        self.systeminfo = []

        self.setup_config()

        # when creating product environment, invoke `IEnvironmentSetupParticipant.environment_created`
        # for all setup participants that don't support multi product environments
        if create:
            for participant in self.product_setup_participants:
                with ComponentEnvironmentContext(self, participant):
                    participant.environment_created()
Exemplo n.º 30
0
    def _upgrade_system_tables(self, db, create_temp_table):
        # migrate system table (except wiki which is handled separately)
        # to a new schema
        # - create tables with the new schema
        # - populate system tables with global configuration for each product
        # - exception is permission table where permissions
        #   are also populated in global scope
        #
        # permission table specifics: 'anonymous' and 'authenticated' users
        # should by default have a PRODUCT_VIEW permission for all products
        self.log.info("Migrating system tables to a new schema")
        for table in self.MIGRATE_TABLES:
            if table == 'wiki':
                continue
            temp_table_name, cols = create_temp_table(table)
            for product in Product.select(self.env):
                self.log.info("Populating table '%s' for product '%s' ('%s')",
                              table, product.name, product.prefix)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, product.prefix, temp_table_name))
                if table == 'permission':
                    db.executemany(
                        """INSERT INTO permission (username, action, product)
                           VALUES (%s, %s, %s)""",
                        [('anonymous', 'PRODUCT_VIEW', product.prefix),
                         ('authenticated', 'PRODUCT_VIEW', product.prefix)])

            if table == 'permission':
                self.log.info("Populating table '%s' for global scope", table)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, '', temp_table_name))
            self._drop_temp_table(db, temp_table_name)
        db.executemany(
            """INSERT INTO permission (username, action, product)
                VALUES (%s, %s, %s)""",
            [('anonymous', 'PRODUCT_VIEW', ''),
             ('authenticated', 'PRODUCT_VIEW', '')])
Exemplo n.º 31
0
    def find_ticket(self, ticket_spec):
        ticket = None
        m = re.match(r'#?(?:(?P<pid>[^-]+)-)?(?P<tid>\d+)', ticket_spec)
        if m:
            pid = m.group('pid')
            tid = m.group('tid')
            if pid:
                try:
                    env = ProductEnvironment(self.env.parent, pid)
                    ticket = Ticket(env, tid)
                except:
                    pass
            else:
                try:
                    ticket = Ticket(self.env, tid)
                except ResourceNotFound:
                    # ticket not found in current product, try all other products
                    for p in Product.select(self.env):
                        if p.prefix != self.env.product.prefix:
                            # TODO: check for PRODUCT_VIEW permissions
                            penv = ProductEnvironment(self.env.parent,
                                                      p.prefix)
                            try:
                                ticket = Ticket(penv, tid)
                            except ResourceNotFound:
                                pass
                            else:
                                break

        # ticket still not found, use fallback for <prefix>:ticket:<id> syntax
        if ticket is None:
            try:
                resource = ResourceIdSerializer.get_resource_by_id(ticket_spec)
                ticket = self._create_ticket_by_full_id(resource)
            except:
                raise NoSuchTicketError
        return ticket
Exemplo n.º 32
0
    def _upgrade_system_tables(self, db, create_temp_table):
        # migrate system table (except wiki which is handled separately)
        # to a new schema
        # - create tables with the new schema
        # - populate system tables with global configuration for each product
        # - exception is permission table where permissions
        #   are also populated in global scope
        #
        # permission table specifics: 'anonymous' and 'authenticated' users
        # should by default have a PRODUCT_VIEW permission for all products
        self.log.info("Migrating system tables to a new schema")
        for table in self.MIGRATE_TABLES:
            if table == 'wiki':
                continue
            temp_table_name, cols = create_temp_table(table)
            for product in Product.select(self.env):
                self.log.info("Populating table '%s' for product '%s' ('%s')",
                              table, product.name, product.prefix)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, product.prefix, temp_table_name))
                if table == 'permission':
                    db.executemany(
                        """INSERT INTO permission (username, action, product)
                           VALUES (%s, %s, %s)""",
                        [('anonymous', 'PRODUCT_VIEW', product.prefix),
                         ('authenticated', 'PRODUCT_VIEW', product.prefix)])

            if table == 'permission':
                self.log.info("Populating table '%s' for global scope", table)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, '', temp_table_name))
            self._drop_temp_table(db, temp_table_name)
        db.executemany(
            """INSERT INTO permission (username, action, product)
                VALUES (%s, %s, %s)""",
            [('anonymous', 'PRODUCT_VIEW', ''),
             ('authenticated', 'PRODUCT_VIEW', '')])
Exemplo n.º 33
0
 def process_request(self, req):
     """process request handler"""
     
     req.perm.require('PRODUCT_VIEW')
     pid = req.args.get('productid', None)
     if pid:
         req.perm('product', pid).require('PRODUCT_VIEW')
     action = req.args.get('action', 'view')
     
     products = [p for p in Product.select(self.env)
                 if 'PRODUCT_VIEW' in req.perm(p.resource)]
     
     if pid is not None:
         add_link(req, 'up', req.href.products(), _('Products'))
     
     try:
         product = Product(self.env, {'prefix': pid})
     except ResourceNotFound:
         product = Product(self.env)
     
     data = {'product': product, 
             'context': web_context(req, product.resource)}
     
     if req.method == 'POST':
         if req.args.has_key('cancel'):
             req.redirect(req.href.products(product.prefix))
         elif action == 'edit':
             return self._do_save(req, product)
         elif action == 'delete':
             req.perm(product.resource).require('PRODUCT_DELETE')
             retarget_to = req.args.get('retarget', None)
             name = product.name
             product.delete(resources_to=retarget_to)
             add_notice(req, _('The product "%(n)s" has been deleted.',
                               n = name))
             req.redirect(req.href.products())
     elif action in ('new', 'edit'):
         return self._render_editor(req, product)
     elif action == 'delete':
         req.perm(product.resource).require('PRODUCT_DELETE')
         return 'product_delete.html', data, None
     
     if pid is None:
         data = {'products': products,
                 'context': web_context(req, Resource('products', None))}
         return 'product_list.html', data, None
     
     def add_product_link(rel, product):
         href = req.href.products(product.prefix)
         add_link(req, rel, href, _('Product "%(name)s"',
                                    name=product.name))
     
     idx = [i for i, p in enumerate(products) if p.name == product.name]
     if idx:
         idx = idx[0]
         if idx > 0:
             add_product_link('first', products[0])
             add_product_link('prev', products[idx - 1])
         if idx < len(products) - 1:
             add_product_link('next', products[idx + 1])
             add_product_link('last', products[-1])        
     prevnext_nav(req, _('Previous Product'), _('Next Product'),
                  _('Back to Product List'))
     return 'product_view.html', data, None
Exemplo n.º 34
0
 def load_product(prefix):
     products = Product.select(self.env, where={'prefix': prefix})
     if not products:
         raise LookupError('Missing product %s' % (prefix, ))
     else:
         return products[0]
Exemplo n.º 35
0
 def load_product(self, prefix):
     products = Product.select(self.env, where={'prefix' : prefix})
     if not products:
         raise AdminCommandError('Unknown product %s' % (prefix,))
     return products[0]
Exemplo n.º 36
0
    def test_upgrade_creates_default_product(self):
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)
Exemplo n.º 37
0
    def process_request(self, req):
        """process request handler"""

        req.perm.require('PRODUCT_VIEW')
        pid = req.args.get('productid', None)
        action = req.args.get('action', 'view')

        products = [
            p for p in Product.select(self.env)
            if 'PRODUCT_VIEW' in req.perm(p.resource)
        ]

        if pid is not None:
            add_link(req, 'up', req.href.products(), _('Products'))

        try:
            product = Product(self.env, {'prefix': pid})
        except ResourceNotFound:
            product = Product(self.env)

        data = {'product': product}

        if req.method == 'POST':
            if req.args.has_key('cancel'):
                req.redirect(req.href.products(product.prefix))
            elif action == 'edit':
                return self._do_save(req, product)
            elif action == 'delete':
                req.perm(product.resource).require('PRODUCT_DELETE')
                retarget_to = req.args.get('retarget', None)
                name = product.name
                product.delete(resources_to=retarget_to)
                add_notice(req,
                           _('The product "%(n)s" has been deleted.', n=name))
                req.redirect(req.href.products())
        elif action in ('new', 'edit'):
            return self._render_editor(req, product)
        elif action == 'delete':
            req.perm(product.resource).require('PRODUCT_DELETE')
            return 'product_delete.html', data, None

        if pid is None:
            data = {'products': products}
            return 'product_list.html', data, None

        def add_product_link(rel, product):
            href = req.href.products(product.prefix)
            add_link(req, rel, href, _('Product "%(name)s"',
                                       name=product.name))

        idx = [i for i, p in enumerate(products) if p.name == product.name]
        if idx:
            idx = idx[0]
            if idx > 0:
                add_product_link('first', products[0])
                add_product_link('prev', products[idx - 1])
            if idx < len(products) - 1:
                add_product_link('next', products[idx + 1])
                add_product_link('last', products[-1])
        prevnext_nav(req, _('Previous Product'), _('Next Product'),
                     _('Back to Product List'))
        return 'product_view.html', data, None
Exemplo n.º 38
0
 def resource_exists(self, resource):
     """Check whether product exists physically.
     """
     products = Product.select(self.env, where={'name' : resource.id})
     return bool(products)
Exemplo n.º 39
0
 def test_delete_twice(self):
     """test that we error when deleting twice on the same key"""
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     product.delete()
     
     self.assertRaises(TracError, product.delete)
Exemplo n.º 40
0
 def _replace_product_on_ticket_with_product_prefix(self, db):
     for prod in Product.select(self.env):
         db("""UPDATE ticket SET product=%s
                       WHERE product=%s""", (prod.prefix, prod.name))
Exemplo n.º 41
0
def get_products(env):
    return [p.prefix for p in Product.select(env)]
Exemplo n.º 42
0
    def _render_admin_panel(self, req, cat, page, product):
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        description = req.args.get('description', '')
        prefix = req.args.get('prefix') if product is None else product
        owner = req.args.get('owner')
        keys = {'prefix': prefix}
        field_data = {
            'name': name,
            'description': description,
            'owner': owner,
        }

        # Detail view?
        if product:
            prod = Product(self.env, keys)
            if req.method == 'POST':
                if req.args.get('save'):
                    req.perm.require('PRODUCT_MODIFY')
                    prod.update_field_dict(field_data)
                    prod.update()
                    add_notice(req, _('Your changes have been saved.'))
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('cancel'):
                    req.redirect(req.href.admin(cat, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'product': prod}
        else:
            default = self.config.get('ticket', 'default_product')
            if req.method == 'POST':
                # Add Product
                if req.args.get('add') and req.args.get('prefix'):
                    req.perm.require('PRODUCT_CREATE')
                    if not owner:
                        add_warning(req, _('All fields are required!'))
                        req.redirect(req.href.admin(cat, page))

                    try:
                        prod = Product(self.env, keys)
                    except ResourceNotFound:
                        prod = Product(self.env)
                        prod.update_field_dict(keys)
                        prod.update_field_dict(field_data)
                        prod.insert()
                        add_notice(
                            req,
                            _('The product "%(id)s" has been added.',
                              id=prefix))
                        req.redirect(req.href.admin(cat, page))
                    else:
                        if prod.prefix is None:
                            raise TracError(_('Invalid product id.'))
                        raise TracError(
                            _("Product %(id)s already exists.", id=prefix))

                # Remove product
                elif req.args.get('remove'):
                    raise TracError(_('Product removal is not allowed!'))

                # Set default product
                elif req.args.get('apply'):
                    prefix = req.args.get('default')
                    if prefix and prefix != default:
                        self.log.info("Setting default product to %s", prefix)
                        self.config.set('ticket', 'default_product', prefix)
                        _save_config(self.config, req, self.log)
                        req.redirect(req.href.admin(cat, page))

            products = Product.select(self.env)
            data = {'view': 'list', 'products': products, 'default': default}
        if self.config.getbool('ticket', 'restrict_owner'):
            perm = PermissionSystem(self.env)

            def valid_owner(username):
                return perm.get_user_permissions(username).get('TICKET_MODIFY')

            data['owners'] = [
                username
                for username, name, email in self.env.get_known_users()
                if valid_owner(username)
            ]
            data['owners'].insert(0, '')
            data['owners'].sort()
        else:
            data['owners'] = None
        return 'admin_products.html', data
Exemplo n.º 43
0
 def _do_product_list(self):
     if not isinstance(self.env, ProductEnvironment):
         print_table(
             [(p.prefix, p.owner, p.name)
              for p in Product.select(self.env)],
             [_('Prefix'), _('Owner'), _('Name')])
Exemplo n.º 44
0
 def load_product(self, prefix):
     products = Product.select(self.env, where={'prefix': prefix})
     if not products:
         raise AdminCommandError('Unknown product %s' % (prefix, ))
     return products[0]
Exemplo n.º 45
0
    def _render_admin_panel(self, req, cat, page, product):
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        description = req.args.get('description','')
        prefix = req.args.get('prefix') if product is None else product
        owner = req.args.get('owner')
        keys = {'prefix':prefix}
        field_data = {'name':name,
                      'description':description,
                      'owner':owner,
                      }
        data = {}

        # Detail view?
        if product:
            prod = Product(self.env, keys)
            if req.method == 'POST':
                if req.args.get('save'):
                    req.perm.require('PRODUCT_MODIFY')
                    prod.update_field_dict(field_data)
                    prod.update(req.authname)
                    add_notice(req, _('Your changes have been saved.'))
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('cancel'):
                    req.redirect(req.href.admin(cat, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'product': prod}
        else:
            default = self.config.get('ticket', 'default_product')
            if req.method == 'POST':
                # Add Product
                if req.args.get('add'):
                    req.perm.require('PRODUCT_CREATE')
                    if not (prefix and name and owner):
                        if not prefix:
                            add_warning(req, _("You must provide a prefix "
                                               "for the product."))
                        if not name:
                            add_warning(req, _("You must provide a name "
                                               "for the product."))
                        if not owner:
                            add_warning(req, _("You must provide an owner "
                                               "for the product."))
                        data['prefix'] = prefix
                        data['name'] = name
                        data['owner'] = owner
                    else:
                        try:
                            prod = Product(self.env, keys)
                        except ResourceNotFound:
                            prod = Product(self.env)
                            prod.update_field_dict(keys)
                            prod.update_field_dict(field_data)
                            prod.insert()
                            add_notice(req, _('The product "%(id)s" has been '
                                              'added.', id=prefix))
                            req.redirect(req.href.admin(cat, page))
                        else:
                            if prod.prefix is None:
                                raise TracError(_('Invalid product id.'))
                            raise TracError(_("Product %(id)s already exists.",
                                              id=prefix))

                # Remove product
                elif req.args.get('remove'):
                    raise TracError(_('Product removal is not allowed!'))

                # Set default product
                elif req.args.get('apply'):
                    prefix = req.args.get('default')
                    if prefix and prefix != default:
                        self.log.info("Setting default product to %s",
                                      prefix)
                        self.config.set('ticket', 'default_product',
                                        prefix)
                        _save_config(self.config, req, self.log)
                        req.redirect(req.href.admin(cat, page))

                # Clear default product
                elif req.args.get('clear'):
                    self.log.info("Clearing default product")
                    self.config.set('ticket', 'default_product', '')
                    _save_config(self.config, req, self.log)
                    req.redirect(req.href.admin(cat, page))

            data['view'] = 'list'
            data['products'] = Product.select(self.env)
            data['default'] = default
        if self.config.getbool('ticket', 'restrict_owner'):
            perm = PermissionSystem(self.env)
            def valid_owner(username):
                return perm.get_user_permissions(username).get('TICKET_MODIFY')
            data['owners'] = [username for username, name, email
                              in self.env.get_known_users()
                              if valid_owner(username)]
            data['owners'].insert(0, '')
            data['owners'].sort()
        else:
            data['owners'] = None
        return 'admin_products.html', data
Exemplo n.º 46
0
 def all_product_envs(self):
     return [ProductEnvironment(self, product) for product in Product.select(self)]
Exemplo n.º 47
0
 def resource_exists(self, resource):
     """Check whether product exists physically.
     """
     products = Product.select(self.env, where={'name' : resource.id})
     return bool(products)
Exemplo n.º 48
0
    def test_delete_twice(self):
        """test that we error when deleting twice on the same key"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        self.assertRaises(TracError, product.delete)
Exemplo n.º 49
0
 def load_product(prefix):
     products = Product.select(self.env, where={'prefix' : prefix})
     if not products:
         raise LookupError('Missing product %s' % (prefix,))
     else:
         return products[0]
Exemplo n.º 50
0
    def _do_save(self, req, product):
        """common processing for product save events"""
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        prefix = req.args.get('prefix')
        description = req.args.get('description', '')

        owner = req.args.get('owner') or req.authname
        keys = {'prefix': prefix}
        field_data = {
            'name': name,
            'description': description,
            'owner': owner,
        }

        warnings = []

        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        if product._exists:
            if name != product.name and Product.select(self.env,
                                                       where={'name': name}):
                warn(
                    _(
                        'A product with name "%(name)s" already exists, please '
                        'choose a different name.',
                        name=name))
            elif not name:
                warn(_('You must provide a name for the product.'))
            else:
                req.perm.require('PRODUCT_MODIFY')
                product.update_field_dict(field_data)
                product.update(req.authname)
                add_notice(req, _('Your changes have been saved.'))
        else:
            req.perm.require('PRODUCT_CREATE')

            if not prefix:
                warn(_('You must provide a prefix for the product.'))
            elif Product.select(self.env, where={'prefix': prefix}):
                warn(
                    _(
                        'Product "%(id)s" already exists, please choose another '
                        'prefix.',
                        id=prefix))
            if not name:
                warn(_('You must provide a name for the product.'))
            elif Product.select(self.env, where={'name': name}):
                warn(
                    _(
                        'A product with name "%(name)s" already exists, please '
                        'choose a different name.',
                        name=name))

            if not warnings:
                prod = Product(self.env)
                prod.update_field_dict(keys)
                prod.update_field_dict(field_data)
                prod.insert()
                add_notice(
                    req, _('The product "%(id)s" has been added.', id=prefix))

        if warnings:
            product.update_field_dict(keys)
            product.update_field_dict(field_data)
            return self._render_editor(req, product)
        req.redirect(req.href.products(prefix))
Exemplo n.º 51
0
 def all_product_envs(self):
     return [
         ProductEnvironment(self, product)
         for product in Product.select(self)
     ]
Exemplo n.º 52
0
 def _replace_product_on_ticket_with_product_prefix(self, db):
     for prod in Product.select(self.env):
         db("""UPDATE ticket SET product=%s
                       WHERE product=%s""", (prod.prefix, prod.name))
Exemplo n.º 53
0
 def _do_product_list(self):
     if not isinstance(self.env, ProductEnvironment):
         print_table([(p.prefix, p.owner, p.name)
                      for p in Product.select(self.env)],
                     [_('Prefix'), _('Owner'), _('Name')])
Exemplo n.º 54
0
def get_products(env):
    return [p.prefix for p in Product.select(env)]
Exemplo n.º 55
0
    def test_upgrade_creates_default_product(self):
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)