a/Allura/allura/model/project.py b/Allura/allura/model/project.py
...
...
16
16
17
from allura.lib import helpers as h
17
from allura.lib import helpers as h
18
from allura.lib import plugin
18
from allura.lib import plugin
19
from allura.lib import exceptions
19
from allura.lib import exceptions
20
from allura.lib import security
20
from allura.lib import security
21
from allura.lib.security import has_access
22
23
try:
24
    from forgewiki import ForgeWikiApp
25
except ImportError:
26
    ForgeWikiApp = None
21
27
22
from .session import main_orm_session
28
from .session import main_orm_session
23
from .session import project_doc_session, project_orm_session
29
from .session import project_doc_session, project_orm_session
24
from .neighborhood import Neighborhood
30
from .neighborhood import Neighborhood
25
from .auth import ProjectRole
31
from .auth import ProjectRole
...
...
93
    _id=FieldProperty(S.ObjectId)
99
    _id=FieldProperty(S.ObjectId)
94
    parent_id = FieldProperty(S.ObjectId, if_missing=None)
100
    parent_id = FieldProperty(S.ObjectId, if_missing=None)
95
    neighborhood_id = ForeignIdProperty(Neighborhood)
101
    neighborhood_id = ForeignIdProperty(Neighborhood)
96
    shortname = FieldProperty(str)
102
    shortname = FieldProperty(str)
97
    name=FieldProperty(str)
103
    name=FieldProperty(str)
104
    notifications_disabled = FieldProperty(bool)
98
    show_download_button=FieldProperty(bool, if_missing=True)
105
    show_download_button=FieldProperty(bool, if_missing=True)
99
    short_description=FieldProperty(str, if_missing='')
106
    short_description=FieldProperty(str, if_missing='')
100
    description=FieldProperty(str, if_missing='')
107
    description=FieldProperty(str, if_missing='')
101
    homepage_title=FieldProperty(str, if_missing='')
108
    homepage_title=FieldProperty(str, if_missing='')
102
    external_homepage=FieldProperty(str, if_missing='')
109
    external_homepage=FieldProperty(str, if_missing='')
...
...
436
        if not h.re_path_portion.match(name):
443
        if not h.re_path_portion.match(name):
437
            raise exceptions.ToolError, 'Mount point "%s" is invalid' % name
444
            raise exceptions.ToolError, 'Mount point "%s" is invalid' % name
438
        provider = plugin.ProjectRegistrationProvider.get()
445
        provider = plugin.ProjectRegistrationProvider.get()
439
        return provider.register_subproject(self, name, user or c.user, install_apps)
446
        return provider.register_subproject(self, name, user or c.user, install_apps)
440
447
448
    def ordered_mounts(self, include_search=False):
449
        '''Returns an array of a projects mounts (tools and sub-projects) in
450
        toolbar order.'''
451
        result = []
452
        for sub in self.direct_subprojects:
453
            result.append({'ordinal':sub.ordinal, 'sub':sub})
454
        for ac in self.app_configs:
455
            if include_search or ac.tool_name != 'search':
456
                ordinal = ac.options.get('ordinal', 0)
457
                result.append({'ordinal':ordinal, 'ac':ac})
458
        return sorted(result, key=lambda e: e['ordinal'])
459
460
    def first_mount(self, required_access=None):
461
        '''Returns the first (toolbar order) mount, or the first mount to
462
        which the user has the required access.'''
463
        mounts = self.ordered_mounts()
464
        if mounts and required_access is None:
465
            return mounts[0]
466
        for mount in mounts:
467
            if 'sub' in mount:
468
                obj = mount['sub']
469
            elif 'ac' in mount:
470
                obj = self.app_instance(mount['ac'])
471
            else:
472
                continue
473
            if has_access(obj, required_access):
474
                return mount
475
        return None
476
441
    def delete(self):
477
    def delete(self):
442
        # Cascade to subprojects
478
        # Cascade to subprojects
443
        for sp in self.direct_subprojects:
479
        for sp in self.direct_subprojects:
444
            sp.delete()
480
            sp.delete()
445
        # Cascade to app configs
481
        # Cascade to app configs
...
...
481
        is_private_project=False):
517
        is_private_project=False):
482
        from allura import model as M
518
        from allura import model as M
483
        if users is None: users = [ c.user ]
519
        if users is None: users = [ c.user ]
484
        if apps is None:
520
        if apps is None:
485
            if is_user_project:
521
            if is_user_project:
486
                apps = [('profile', 'profile'),
522
                apps = [('profile', 'profile', 'Profile'),
487
                        ('admin', 'admin'),
523
                        ('admin', 'admin', 'Admin'),
488
                        ('search', 'search')]
524
                        ('search', 'search', 'Search')]
489
            else:
525
            else:
490
                apps = [('home', 'home'),
526
                apps = [('Wiki', 'home', 'Home'),
491
                        ('admin', 'admin'),
527
                        ('admin', 'admin', 'Admin'),
492
                        ('search', 'search')]
528
                        ('search', 'search', 'Search')]
493
        with h.push_config(c, project=self, user=users[0]):
529
        with h.push_config(c, project=self, user=users[0]):
494
            # Install default named roles (#78)
530
            # Install default named roles (#78)
495
            root_project_id=self.root_project._id
531
            root_project_id=self.root_project._id
496
            role_admin = M.ProjectRole.upsert(name='Admin', project_id=root_project_id)
532
            role_admin = M.ProjectRole.upsert(name='Admin', project_id=root_project_id)
497
            role_developer = M.ProjectRole.upsert(name='Developer', project_id=root_project_id)
533
            role_developer = M.ProjectRole.upsert(name='Developer', project_id=root_project_id)
...
...
511
                for perm in self.permissions ]
547
                for perm in self.permissions ]
512
            for user in users:
548
            for user in users:
513
                pr = user.project_role()
549
                pr = user.project_role()
514
                pr.roles = [ role_admin._id, role_developer._id, role_member._id ]
550
                pr.roles = [ role_admin._id, role_developer._id, role_member._id ]
515
            # Setup apps
551
            # Setup apps
516
            for ep_name, mount_point in apps:
552
            for i, (ep_name, mount_point, label) in enumerate(apps):
517
                self.install_app(ep_name, mount_point)
553
                self.install_app(ep_name, mount_point, label, ordinal=i)
554
            if ForgeWikiApp is not None:
555
                home_app = self.app_instance('home')
556
                if isinstance(home_app, ForgeWikiApp):
557
                    home_app.show_discussion = False
558
                    home_app.show_left_bar = False
518
            self.database_configured = True
559
            self.database_configured = True
519
            ThreadLocalORMSession.flush_all()
560
            ThreadLocalORMSession.flush_all()
520
561
521
    def add_user(self, user, role_names):
562
    def add_user(self, user, role_names):
522
        'Convenience method to add member with the given role(s).'
563
        'Convenience method to add member with the given role(s).'