コード例 #1
0
 def sidebar_menu(self):
     try:
         l = []
         moderate_link = None
         forum_links = []
         forums = DM.Forum.query.find(
             dict(app_config_id=c.app.config._id,
                  parent_id=None,
                  deleted=False))
         for f in forums:
             if has_access(f, 'read')():
                 if f.url() in request.url and h.has_access(f,
                                                            'moderate')():
                     moderate_link = SitemapEntry(
                         'Moderate',
                         "%smoderate/" % f.url(),
                         ui_icon=g.icons['pencil'],
                         small=DM.ForumPost.query.find({
                             'discussion_id': f._id,
                             'status': {
                                 '$ne': 'ok'
                             }
                         }).count())
                 forum_links.append(
                     SitemapEntry(f.name, f.url(), small=f.num_topics))
         url = c.app.url + 'create_topic/'
         url = h.urlquote(url + c.forum.shortname
                          if getattr(c, 'forum', None) and c.forum else url)
         l.append(SitemapEntry('Create Topic', url,
                               ui_icon=g.icons['plus']))
         if has_access(c.app, 'configure')():
             l.append(
                 SitemapEntry('Add Forum',
                              c.app.url + 'new_forum',
                              ui_icon=g.icons['conversation']))
             l.append(
                 SitemapEntry('Admin Forums',
                              c.project.url() + 'admin/' +
                              self.config.options.mount_point + '/forums',
                              ui_icon=g.icons['pencil']))
         if moderate_link:
             l.append(moderate_link)
         # if we are in a thread and not anonymous, provide placeholder links to use in js
         if '/thread/' in request.url and c.user not in (
                 None, M.User.anonymous()):
             l.append(
                 SitemapEntry('Mark as Spam',
                              'flag_as_spam',
                              ui_icon=g.icons['flag'],
                              className='sidebar_thread_spam'))
         if forum_links:
             l.append(SitemapEntry('Forums'))
             l = l + forum_links
         l.append(SitemapEntry('Help'))
         l.append(
             SitemapEntry('Formatting Help', c.app.url + 'markdown_syntax'))
         return l
     except:  # pragma no cover
         log.exception('sidebar_menu')
         return []
コード例 #2
0
 def test_deny_access_for_single_user(self):
     wiki = c.project.app_instance('wiki')
     user = M.User.by_username('test-user')
     assert has_access(wiki, 'read', user)()
     wiki.acl.append(M.ACE.deny(M.ProjectRole.by_user(user, upsert=True)._id, 'read', 'Spammer'))
     Credentials.get().clear()
     assert not has_access(wiki, 'read', user)()
コード例 #3
0
    def sidebar_menu(self):
        links = []
        admin_url = c.project.url()+'admin/'


        if c.project.is_nbhd_project:
            links.append(SitemapEntry('Add Project', c.project.url()+'add_project', ui_icon=g.icons['plus']))
            nbhd_admin_url = c.project.neighborhood.url()+'_admin/'
            links = links + [
                     SitemapEntry('Neighborhood'),
                     SitemapEntry('Overview', nbhd_admin_url+'overview'),
                     SitemapEntry('Awards', nbhd_admin_url+'accolades')]
        else:
            links += [SitemapEntry('Metadata', admin_url+'overview'),]
            if c.project.neighborhood.name != "Users":
                links += [
                    SitemapEntry('Screenshots', admin_url+'screenshots'),
                    SitemapEntry('Categorization', admin_url+'trove')
                ]
        links.append(SitemapEntry('Tools', admin_url+'tools'))
        if c.project.is_root and has_access(c.project, 'admin')():
            links.append(SitemapEntry('User Permissions', admin_url+'groups/'))
        if not c.project.is_root and has_access(c.project, 'admin')():
            links.append(SitemapEntry('Permissions', admin_url+'permissions/'))
        if len(c.project.neighborhood_invitations):
            links.append(SitemapEntry('Invitation(s)', admin_url+'invitations'))
        links.append(SitemapEntry('Audit Trail', admin_url+ 'audit/'))
        if c.project.is_nbhd_project:
            links.append(SitemapEntry('Statistics', nbhd_admin_url+ 'stats/'))
            links.append(None)
            links.append(SitemapEntry('Help', nbhd_admin_url+ 'help/'))
        return links
コード例 #4
0
def test_artifact():
    pg = WM.Page(title='TestPage1')
    assert pg.project == c.project
    assert pg.project_id == c.project._id
    assert pg.app.config == c.app.config
    assert pg.app_config == c.app.config
    u = M.User.query.get(username='******')
    pr = u.project_role()
    ThreadLocalORMSession.flush_all()
    REGISTRY.register(allura.credentials, allura.lib.security.Credentials())
    assert not security.has_access(pg, 'delete')(user=u)
    pg.acl.append(M.ACE.allow(pr._id, 'delete'))
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert security.has_access(pg, 'delete')(user=u)
    pg.acl.pop()
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert not security.has_access(pg, 'delete')(user=u)
    idx = pg.index()
    assert 'title' in idx
    assert 'url_s' in idx
    assert 'project_id_s' in idx
    assert 'mount_point_s' in idx
    assert 'type_s' in idx
    assert 'id' in idx
    assert idx['id'] == pg.index_id()
    assert 'text' in idx
    assert 'TestPage' in pg.shorthand_id()
    assert pg.link_text() == pg.shorthand_id()
コード例 #5
0
    def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None):
        """
        Create a Feed item.  Returns the item.
        But if anon doesn't have read access, create does not happen and None is returned
        """
        # TODO: fix security system so we can do this correctly and fast
        from allura import model as M

        anon = M.User.anonymous()
        if not security.has_access(artifact, "read", user=anon):
            return
        if not security.has_access(c.project, "read", user=anon):
            return
        idx = artifact.index()
        if author is None:
            author = c.user
        if author_name is None:
            author_name = author.get_pref("display_name")
        if title is None:
            title = "%s modified by %s" % (idx["title_s"], author_name)
        if description is None:
            description = title
        item = cls(
            ref_id=artifact.index_id(),
            neighborhood_id=artifact.app_config.project.neighborhood_id,
            project_id=artifact.app_config.project_id,
            app_config_id=artifact.app_config_id,
            tool_name=artifact.app_config.tool_name,
            title=title,
            description=description,
            link=artifact.url(),
            author_name=author_name,
            author_link=author_link or author.url(),
        )
        return item
コード例 #6
0
def test_artifact():
    pg = WM.Page(title='TestPage1')
    assert pg.project == c.project
    assert pg.project_id == c.project._id
    assert pg.app.config == c.app.config
    assert pg.app_config == c.app.config
    u = M.User.query.get(username='******')
    pr = M.ProjectRole.by_user(u, upsert=True)
    ThreadLocalORMSession.flush_all()
    REGISTRY.register(allura.credentials, allura.lib.security.Credentials())
    assert not security.has_access(pg, 'delete')(user=u)
    pg.acl.append(M.ACE.allow(pr._id, 'delete'))
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert security.has_access(pg, 'delete')(user=u)
    pg.acl.pop()
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert not security.has_access(pg, 'delete')(user=u)
    idx = pg.index()
    assert 'title' in idx
    assert 'url_s' in idx
    assert 'project_id_s' in idx
    assert 'mount_point_s' in idx
    assert 'type_s' in idx
    assert 'id' in idx
    assert idx['id'] == pg.index_id()
    assert 'text' in idx
    assert 'TestPage' in pg.shorthand_id()
    assert pg.link_text() == pg.shorthand_id()
コード例 #7
0
 def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None):
     """
     Create a Feed item.  Returns the item.
     But if anon doesn't have read access, create does not happen and None is returned
     """
     # TODO: fix security system so we can do this correctly and fast
     from allura import model as M
     anon = M.User.anonymous()
     if not security.has_access(artifact, 'read', user=anon):
         return
     if not security.has_access(c.project, 'read', user=anon):
         return
     idx = artifact.index()
     if author is None:
         author = c.user
     if author_name is None:
         author_name = author.get_pref('display_name')
     if title is None:
         title='%s modified by %s' % (idx['title_s'], author_name)
     if description is None: description = title
     item = cls(
         ref_id=artifact.index_id(),
         neighborhood_id=artifact.app_config.project.neighborhood_id,
         project_id=artifact.app_config.project_id,
         app_config_id=artifact.app_config_id,
         tool_name=artifact.app_config.tool_name,
         title=title,
         description=description,
         link=artifact.url(),
         author_name=author_name,
         author_link=author_link or author.url())
     return item
コード例 #8
0
ファイル: test_artifact.py プロジェクト: Bitergia/allura
def test_artifact():
    pg = WM.Page(title="TestPage1")
    assert pg.project == c.project
    assert pg.project_id == c.project._id
    assert pg.app.config == c.app.config
    assert pg.app_config == c.app.config
    u = M.User.query.get(username="******")
    pr = u.project_role()
    ThreadLocalORMSession.flush_all()
    REGISTRY.register(allura.credentials, allura.lib.security.Credentials())
    assert not security.has_access(pg, "delete")(user=u)
    pg.acl.append(M.ACE.allow(pr._id, "delete"))
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert security.has_access(pg, "delete")(user=u)
    pg.acl.pop()
    ThreadLocalORMSession.flush_all()
    c.memoize_cache = {}
    assert not security.has_access(pg, "delete")(user=u)
    idx = pg.index()
    assert "title_s" in idx
    assert "url_s" in idx
    assert "project_id_s" in idx
    assert "mount_point_s" in idx
    assert "type_s" in idx
    assert "id" in idx
    assert idx["id"] == pg.index_id()
    assert "text" in idx
    assert "TestPage" in pg.shorthand_id()
    assert pg.link_text() == pg.shorthand_id()
コード例 #9
0
ファイル: forum_main.py プロジェクト: Bitergia/allura
 def sidebar_menu(self):
     try:
         l = []
         moderate_link = None
         forum_links = []
         forums = DM.Forum.query.find(dict(
                         app_config_id=c.app.config._id,
                         parent_id=None, deleted=False))
         for f in forums:
             if has_access(f,'read')():
                 if f.url() in request.url and h.has_access(f, 'moderate')():
                     moderate_link = SitemapEntry('Moderate', "%smoderate/" % f.url(), ui_icon=g.icons['pencil'],
                     small = DM.ForumPost.query.find({'discussion_id':f._id, 'status':{'$ne': 'ok'}}).count())
                 forum_links.append(SitemapEntry(f.name, f.url(), small=f.num_topics))
         l.append(SitemapEntry('Create Topic', c.app.url + 'create_topic', ui_icon=g.icons['plus']))
         if has_access(c.app, 'configure')():
             l.append(SitemapEntry('Add Forum', c.app.url + 'new_forum', ui_icon=g.icons['conversation']))
             l.append(SitemapEntry('Admin Forums', c.project.url()+'admin/'+self.config.options.mount_point+'/forums', ui_icon=g.icons['pencil']))
         if moderate_link:
             l.append(moderate_link)
         # if we are in a thread and not anonymous, provide placeholder links to use in js
         if '/thread/' in request.url and c.user not in (None, M.User.anonymous()):
             l.append(SitemapEntry(
                     'Mark as Spam', 'flag_as_spam',
                     ui_icon=g.icons['flag'], className='sidebar_thread_spam'))
         if forum_links:
             l.append(SitemapEntry('Forums'))
             l = l + forum_links
         l.append(SitemapEntry('Help'))
         l.append(SitemapEntry('Formatting Help', c.app.url + 'markdown_syntax'))
         return l
     except: # pragma no cover
         log.exception('sidebar_menu')
         return []
コード例 #10
0
    def sidebar_menu(self):
        links = []
        admin_url = c.project.url() + "admin/"

        if c.project.is_nbhd_project:
            links.append(SitemapEntry("Add Project", c.project.url() + "add_project", ui_icon=g.icons["plus"]))
            nbhd_admin_url = c.project.neighborhood.url() + "_admin/"
            links = links + [
                SitemapEntry("Neighborhood"),
                SitemapEntry("Overview", nbhd_admin_url + "overview"),
                SitemapEntry("Awards", nbhd_admin_url + "accolades"),
            ]
        else:
            links += [SitemapEntry("Metadata", admin_url + "overview")]
            if c.project.neighborhood.name != "Users":
                links += [
                    SitemapEntry("Screenshots", admin_url + "screenshots"),
                    SitemapEntry("Categorization", admin_url + "trove"),
                ]
        links.append(SitemapEntry("Tools", admin_url + "tools"))
        if c.project.is_root and has_access(c.project, "admin")():
            links.append(SitemapEntry("User Permissions", admin_url + "groups/"))
        if not c.project.is_root and has_access(c.project, "admin")():
            links.append(SitemapEntry("Permissions", admin_url + "permissions/"))
        if len(c.project.neighborhood_invitations):
            links.append(SitemapEntry("Invitation(s)", admin_url + "invitations"))
        links.append(SitemapEntry("Audit Trail", admin_url + "audit/"))
        if c.project.is_nbhd_project:
            links.append(SitemapEntry("Statistics", nbhd_admin_url + "stats/"))
            links.append(None)
            links.append(SitemapEntry("Help", nbhd_admin_url + "help/"))
        return links
コード例 #11
0
ファイル: artifact.py プロジェクト: DalavanCloud/allura
 def has_access(cls, artifact):
     # Enable only for development.
     # return True
     from allura import model as M
     anon = M.User.anonymous()
     if not security.has_access(artifact, 'read', user=anon):
         return False
     if not security.has_access(c.project, 'read', user=anon):
         return False
     return True
コード例 #12
0
ファイル: test_security.py プロジェクト: vclisunlang/allura
 def test_deny_access_for_single_user(self):
     wiki = c.project.app_instance('wiki')
     user = M.User.by_username('test-user')
     assert has_access(wiki, 'read', user)()
     wiki.acl.append(
         M.ACE.deny(
             M.ProjectRole.by_user(user, upsert=True)._id, 'read',
             'Spammer'))
     Credentials.get().clear()
     assert not has_access(wiki, 'read', user)()
コード例 #13
0
ファイル: artifact.py プロジェクト: apache/allura
 def has_access(cls, artifact):
     # Enable only for development.
     # return True
     from allura import model as M
     anon = M.User.anonymous()
     if not security.has_access(artifact, 'read', user=anon):
         return False
     if not security.has_access(c.project, 'read', user=anon):
         return False
     return True
コード例 #14
0
    def post(self,
             text,
             message_id=None,
             parent_id=None,
             notify=True,
             notification_text=None,
             timestamp=None,
             ignore_security=False,
             is_meta=False,
             subscribe=False,
             **kw):
        if not ignore_security:
            require_access(self, 'post')
        if subscribe:
            self.primary().subscribe()
        if message_id is None:
            message_id = h.gen_message_id()
        parent = parent_id and self.post_class().query.get(_id=parent_id)
        slug, full_slug = self.post_class().make_slugs(parent, timestamp)
        kwargs = dict(discussion_id=self.discussion_id,
                      full_slug=full_slug,
                      slug=slug,
                      thread_id=self._id,
                      parent_id=parent_id,
                      text=text,
                      status='pending',
                      is_meta=is_meta)
        if timestamp is not None:
            kwargs['timestamp'] = timestamp
        if message_id is not None:
            kwargs['_id'] = message_id
        post = self.post_class()(**kwargs)

        if ignore_security or is_meta:
            spammy = False
        else:
            spammy = self.is_spam(post)
        # unmoderated post -> autoapprove
        # unmoderated post but is spammy -> don't approve it, it goes into moderation
        # moderated post -> moderation
        # moderated post but is spammy -> mark as spam
        if ignore_security or (not spammy
                               and has_access(self, 'unmoderated_post')):
            log.info('Auto-approving message from %s', c.user.username)
            file_info = kw.get('file_info', None)
            post.approve(file_info,
                         notify=notify,
                         notification_text=notification_text)
        elif not has_access(self, 'unmoderated_post') and spammy:
            post.spam(
                submit_spam_feedback=False
            )  # no feedback since we're marking as spam automatically not manually
        else:
            self.notify_moderators(post)
        return post
コード例 #15
0
    def test_render_index(self):
        admin = M.User.query.get(username='******')
        anon = M.User.query.get(username="******")
        for app in M.AppConfig.query.find({'options.mount_point': 'bugs'}):
            assert has_access(app, 'create', admin)
            assert not has_access(app, 'create', anon)

        index_view = self.app.get('/bugs/')
        assert 'No open tickets found.' in index_view
        assert 'Create Ticket' in index_view
        # No 'Create Ticket' button for user without 'create' perm
        r = self.app.get('/bugs/', extra_environ=dict(username='******'))
        assert 'Create Ticket' not in r
コード例 #16
0
 def post(cls,
          artifact,
          title=None,
          description=None,
          author=None,
          author_link=None,
          author_name=None,
          pubdate=None,
          link=None,
          **kw):
     """
     Create a Feed item.  Returns the item.
     But if anon doesn't have read access, create does not happen and None is returned
     """
     # TODO: fix security system so we can do this correctly and fast
     from allura import model as M
     anon = M.User.anonymous()
     if not security.has_access(artifact, 'read', user=anon):
         return
     if not security.has_access(c.project, 'read', user=anon):
         return
     idx = artifact.index()
     if author is None:
         author = c.user
     if author_name is None:
         author_name = author.get_pref('display_name')
     if title is None:
         title = '%s modified by %s' % (h.get_first(idx,
                                                    'title'), author_name)
     if description is None:
         description = title
     if pubdate is None:
         pubdate = datetime.utcnow()
     if link is None:
         link = artifact.url()
     item = cls(ref_id=artifact.index_id(),
                neighborhood_id=artifact.app_config.project.neighborhood_id,
                project_id=artifact.app_config.project_id,
                app_config_id=artifact.app_config_id,
                tool_name=artifact.app_config.tool_name,
                title=title,
                description=g.markdown.convert(description),
                link=link,
                pubdate=pubdate,
                author_name=author_name,
                author_link=author_link or author.url())
     unique_id = kw.pop('unique_id', None)
     if unique_id:
         item.unique_id = unique_id
     return item
コード例 #17
0
    def has_activity_access(self, perm, user):
        """Return True if user has perm access to this object, otherwise
        return False.

        For the purposes of activitystreams, we're saying that the user does
        not have access to a 'comment' activity unless he also has access to
        the artifact on which it was posted (if there is one).
        """
        artifact_access = True
        if self.thread.artifact:
            artifact_access = security.has_access(self.thread.artifact, perm,
                    user, self.thread.artifact.project)

        return artifact_access and security.has_access(self, perm, user,
                self.project)
コード例 #18
0
ファイル: discuss.py プロジェクト: pombreda/allura
    def has_activity_access(self, perm, user):
        """Return True if user has perm access to this object, otherwise
        return False.

        For the purposes of activitystreams, we're saying that the user does
        not have access to a 'comment' activity unless he also has access to
        the artifact on which it was posted (if there is one).
        """
        artifact_access = True
        if self.thread.artifact:
            artifact_access = security.has_access(self.thread.artifact, perm,
                    user, self.thread.artifact.project)

        return artifact_access and security.has_access(self, perm, user,
                self.project)
コード例 #19
0
ファイル: admin_main.py プロジェクト: 00mjk/allura
    def sidebar_menu(self):
        links = []
        admin_url = c.project.url() + 'admin/'

        if c.project.is_nbhd_project:
            links.append(SitemapEntry('Add Project', c.project.url()
                                      + 'add_project', ui_icon=g.icons['add']))
            nbhd_admin_url = c.project.neighborhood.url() + '_admin/'
            links = links + [
                SitemapEntry('Neighborhood'),
                SitemapEntry('Overview', nbhd_admin_url + 'overview'),
                SitemapEntry('Awards', nbhd_admin_url + 'accolades')]
        else:
            links += [
                SitemapEntry('Welcome', admin_url),
                SitemapEntry('Metadata', admin_url + 'overview', className="admin-nav-metadata"),
            ]
            if c.project.neighborhood.name != "Users":
                links += [
                    SitemapEntry('Screenshots', admin_url + 'screenshots'),
                    SitemapEntry('Categorization', admin_url + 'trove')
                ]
        if plugin.ProjectRegistrationProvider.get().registration_date(c.project) < datetime(2016, 6, 1):
            # only show transitional Tools page to older projects that may be used to it
            # no point is showing it to new projects
            links.append(SitemapEntry('Tools', admin_url + 'tools_moved'))
        if asbool(config.get('bulk_export_enabled', True)):
            links.append(SitemapEntry('Export', admin_url + 'export'))
        if c.project.is_root and has_access(c.project, 'admin')():
            links.append(
                SitemapEntry('User Permissions', admin_url + 'groups/', className="admin-nav-user-perms"))
        if not c.project.is_root and has_access(c.project, 'admin')():
            links.append(
                SitemapEntry('Permissions', admin_url + 'permissions/'))
        if len(c.project.neighborhood_invitations):
            links.append(
                SitemapEntry('Invitation(s)', admin_url + 'invitations'))
        links.append(SitemapEntry('Audit Trail', admin_url + 'audit/'))
        if c.project.is_nbhd_project:
            links.append(SitemapEntry('Statistics', nbhd_admin_url + 'stats/'))
            links.append(None)
            links.append(SitemapEntry('Help', nbhd_admin_url + 'help/'))

        for ep_name in sorted(g.entry_points['admin'].keys()):
            admin_extension = g.entry_points['admin'][ep_name]
            admin_extension().update_project_sidebar_menu(links)

        return links
コード例 #20
0
ファイル: auth.py プロジェクト: joequant/allura
    def _auth_repos(self, user):
        def _unix_group_name(neighborhood, shortname):
            path = neighborhood.url_prefix + shortname[len(neighborhood.shortname_prefix) :]
            parts = [p for p in path.split("/") if p]
            if len(parts) == 2 and parts[0] == "p":
                parts = parts[1:]
            return ".".join(reversed(parts))

        repos = []
        for p in user.my_projects():
            for p in [p] + p.direct_subprojects:
                for app in p.app_configs:
                    if not issubclass(g.entry_points["tool"][app.tool_name], RepositoryApp):
                        continue
                    if not has_access(app, "write", user, p):
                        continue
                    repos.append(
                        "/%s/%s/%s"
                        % (
                            app.tool_name.lower(),
                            _unix_group_name(p.neighborhood, p.shortname),
                            app.options["mount_point"],
                        )
                    )
        repos.sort()
        return repos
コード例 #21
0
ファイル: main.py プロジェクト: joequant/allura
 def exfeed(self):
     # self.app.external_feeds_list = ['feed1', 'feed2']
     # log.info("EXFEED: %s" % self.app.external_feeds_list)
     feeds_list = []
     for feed in self.app.external_feeds_list:
         feeds_list.append(feed)
     return dict(app=self.app, feeds_list=feeds_list, allow_config=has_access(self.app, "configure")())
コード例 #22
0
 def has_activity_access(self, perm, user, activity):
     """Return True if user has perm access to this object, otherwise
     return False.
     """
     if self.project is None or getattr(self, 'deleted', False):
         return False
     return security.has_access(self, perm, user, self.project)
コード例 #23
0
ファイル: repository.py プロジェクト: petertsehsun/allura
 def save(self, status=None, **kw):
     if status and self.req.status != status and \
        (has_access(self.req, 'write') or (self.req.creator == c.user and status == 'rejected')):
         self.req.add_meta_post(
             changes={'Status': [self.req.status, status]})
         self.req.status = status
     redirect('.')
コード例 #24
0
 def fork(self, project_id=None, mount_point=None, mount_label=None):
     # this shows the form and handles the submission
     security.require_authenticated()
     if not c.app.forkable: raise exc.HTTPNotFound
     from_repo = c.app.repo
     ThreadLocalORMSession.flush_all()
     ThreadLocalORMSession.close_all()
     from_project = c.project
     to_project = M.Project.query.get(_id=ObjectId(project_id))
     mount_label = mount_label or '%s - %s' % (
         c.project.name, c.app.config.options.mount_label)
     mount_point = (mount_point or from_project.shortname)
     if request.method != 'POST' or not mount_point:
         return dict(from_repo=from_repo,
                     user_project=c.user.private_project(),
                     mount_point=mount_point,
                     mount_label=mount_label)
     else:
         with h.push_config(c, project=to_project):
             if not to_project.database_configured:
                 to_project.configure_project(is_user_project=True)
             security.require(security.has_access(to_project, 'admin'))
             try:
                 to_project.install_app(
                     ep_name=from_repo.tool_name,
                     mount_point=mount_point,
                     mount_label=mount_label,
                     cloned_from_project_id=from_project._id,
                     cloned_from_repo_id=from_repo._id)
                 redirect(to_project.url() + mount_point + '/')
             except exc.HTTPRedirection:
                 raise
             except Exception, ex:
                 flash(str(ex), 'error')
                 redirect(request.referer)
コード例 #25
0
ファイル: main.py プロジェクト: phraniiac/allura
    def index(self,
              title='',
              text='',
              state='draft',
              labels='',
              limit=10,
              page=0,
              **kw):
        if request.method == 'POST':
            require_access(c.app, 'write')
            post = BM.BlogPost.new(title=title,
                                   state=state,
                                   text=text,
                                   labels=labels.split(','),
                                   **kw)
            return exc.HTTPCreated(headers=dict(Location=h.absurl('/rest' +
                                                                  post.url())))

        else:
            result = RootController().index(limit=limit, page=page)
            posts = result['posts']
            post_titles = []
            for post in posts:
                if has_access(post, 'read')():
                    post_titles.append({
                        'title': post.title,
                        'url': h.absurl('/rest' + post.url())
                    })
            return dict(posts=post_titles,
                        count=result['count'],
                        limit=result['limit'],
                        page=result['page'])
コード例 #26
0
ファイル: repository.py プロジェクト: dastanforever/allura
 def save(self, status=None, **kw):
     if status and self.req.status != status and \
        (has_access(self.req, 'write') or (self.req.creator == c.user and status == 'rejected')):
         message = self.tmpl.render(changes={'Status': [self.req.status, status]})
         self.req.discussion_thread.add_post(text=message, is_meta=True)
         self.req.status = status
     redirect('.')
コード例 #27
0
    def search(self, q=None,
               history=None, project=None,
               limit=None, page=0, **kw):
        if project:
            redirect(c.project.url() +
                     'search?' +
                     urlencode(dict(q=q, history=history)))
        results = []
        count = 0
        limit, page, start = g.handle_paging(limit, page, default=25)
        if not q:
            q = ''
        else:
            query = ['is_history_b:%s' % history,
                    'project_id_s:%s' % c.project._id,
                    'mount_point_s:%s' % c.app.config.options.mount_point,
                    'type_s:%s' % ShortUrl.type_s]
            if not has_access(c.app, 'view_private'):
                query.append('private_b:False')
            results = search(q, fq=query)

            if results:
                count = results.hits
        c.search_results = W.search_results
        return dict(q=q, history=history, results=results or [],
                    count=count, limit=limit, page=page)
コード例 #28
0
 def post(self, text, message_id=None, parent_id=None,
          timestamp=None, ignore_security=False, is_meta=False, **kw):
     if not ignore_security:
         require_access(self, 'post')
     if self.ref_id and self.artifact:
         self.artifact.subscribe()
     if message_id is None:
         message_id = h.gen_message_id()
     parent = parent_id and self.post_class().query.get(_id=parent_id)
     slug, full_slug = self.post_class().make_slugs(parent, timestamp)
     kwargs = dict(
         discussion_id=self.discussion_id,
         full_slug=full_slug,
         slug=slug,
         thread_id=self._id,
         parent_id=parent_id,
         text=text,
         status='pending',
         is_meta=is_meta)
     if timestamp is not None:
         kwargs['timestamp'] = timestamp
     if message_id is not None:
         kwargs['_id'] = message_id
     post = self.post_class()(**kwargs)
     if ignore_security or not self.is_spam(post) and has_access(self, 'unmoderated_post')():
         log.info('Auto-approving message from %s', c.user.username)
         file_info = kw.get('file_info', None)
         post.approve(file_info, notify=kw.get('notify', True))
     else:
         self.notify_moderators(post)
     return post
コード例 #29
0
    def paged_query(cls, app_config, user, query, limit=None, page=0, sort=None, deleted=False, **kw):
        """
        Query tickets, filtering for 'read' permission, sorting and paginating the result.

        See also paged_search which does a solr search
        """
        limit, page, start = g.handle_paging(limit, page, default=25)
        q = cls.query.find(dict(query, app_config_id=app_config._id, deleted=deleted))
        q = q.sort('ticket_num', pymongo.DESCENDING)
        if sort:
            field, direction = sort.split()
            if field.startswith('_'):
                field = 'custom_fields.' + field
            direction = dict(
                asc=pymongo.ASCENDING,
                desc=pymongo.DESCENDING)[direction]
            q = q.sort(field, direction)
        q = q.skip(start)
        q = q.limit(limit)
        tickets = []
        count = q.count()
        for t in q:
            if security.has_access(t, 'read', user, app_config.project.root_project):
                tickets.append(t)
            else:
                count = count -1

        return dict(
            tickets=tickets,
            count=count, q=json.dumps(query), limit=limit, page=page, sort=sort,
            **kw)
コード例 #30
0
ファイル: forum.py プロジェクト: AsylumCorp/incubator-allura
 def moderate(self, **kw):
     require_access(self.post.thread, 'moderate')
     if self.thread.discussion.deleted and not has_access(c.app, 'configure')():
         redirect(self.thread.discussion.url() + 'deleted')
     tasks.calc_thread_stats.post(self.post.thread._id)
     tasks.calc_forum_stats(self.post.discussion.shortname)
     super(ForumPostController, self).moderate(**kw)
コード例 #31
0
ファイル: app.py プロジェクト: joequant/allura
    def admin_menu(self, force_options=False):
        """Return the admin menu for this Application.

        Default implementation will return a menu with up to 4 links:

            - 'Permissions', if the current user has admin access to the
                project in which this Application is installed
            - 'Options', if this Application has custom options, or
                ``force_options`` is True
            - 'Rename', for editing this Application's label
            - 'Webhooks', if this Application can trigger any webhooks

        Subclasses should override this method to provide additional admin
        menu items.

        :param force_options: always include an 'Options' link in the menu,
            even if this Application has no custom options
        :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`

        """
        admin_url = c.project.url() + "admin/" + self.config.options.mount_point + "/"
        links = []
        if self.permissions and has_access(c.project, "admin")():
            links.append(SitemapEntry("Permissions", admin_url + "permissions"))
        if force_options or len(self.config_options) > 3:
            links.append(SitemapEntry("Options", admin_url + "options", className="admin_modal"))
        links.append(SitemapEntry("Rename", admin_url + "edit_label", className="admin_modal"))
        if len(self._webhooks) > 0:
            links.append(SitemapEntry("Webhooks", admin_url + "webhooks"))
        return links
コード例 #32
0
ファイル: app.py プロジェクト: apache/incubator-allura
    def edit_label(self):
        """Renders form to update the Application's ``mount_label``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())
コード例 #33
0
def nbhd_lookup_first_path(nbhd, name, current_user, remainder, api=False):
    """
    Resolve first part of a neighborhood url.  May raise 404, redirect, or do other side effects.

    Shared between NeighborhoodController and NeighborhoodRestController

    :param nbhd: neighborhood
    :param name: project or tool name (next part of url)
    :param current_user: a User
    :param remainder: remainder of url
    :param bool api: whether this is handling a /rest/ request or not

    :return: project (to be set as c.project)
    :return: remainder (possibly modified)
    """

    prefix = nbhd.shortname_prefix
    pname = unquote(name)
    provider = plugin.ProjectRegistrationProvider.get()
    try:
        provider.shortname_validator.to_python(pname, check_allowed=False, neighborhood=nbhd)
    except Invalid:
        project = None
    else:
        project = M.Project.query.get(shortname=prefix + pname, neighborhood_id=nbhd._id)
    if project is None and prefix == 'u/':
        # create user-project if it is missing
        user = M.User.query.get(username=pname, disabled=False, pending=False)
        if user:
            project = user.private_project()
            if project.shortname != prefix + pname:
                # might be different URL than the URL requested
                # e.g. if username isn't valid project name and user_project_shortname() converts the name
                new_url = project.url()
                if api:
                    new_url = '/rest' + new_url
                new_url += '/'.join(remainder)
                if request.query_string:
                    new_url += '?' + request.query_string
                redirect(new_url)
    if project is None:
        # look for neighborhood tools matching the URL
        project = nbhd.neighborhood_project
        return project, (pname,) + remainder  # include pname in new remainder, it is actually the nbhd tool path
    if project and prefix == 'u/':
        # make sure user-projects are associated with an enabled user
        user = project.user_project_of
        if not user or user.disabled or user.pending:
            raise exc.HTTPNotFound
    if project.database_configured is False:
        if remainder == ('user_icon',):
            redirect(g.forge_static('images/user.png'))
        elif current_user.username == pname:
            log.info('Configuring %s database for access to %r', pname, remainder)
            project.configure_project(is_user_project=True)
        else:
            raise exc.HTTPNotFound, pname
    if project is None or (project.deleted and not has_access(project, 'update')()):
        raise exc.HTTPNotFound, pname
    return project, remainder
コード例 #34
0
ファイル: rest.py プロジェクト: apache/allura
def nbhd_lookup_first_path(nbhd, name, current_user, remainder, api=False):
    """
    Resolve first part of a neighborhood url.  May raise 404, redirect, or do other side effects.

    Shared between NeighborhoodController and NeighborhoodRestController

    :param nbhd: neighborhood
    :param name: project or tool name (next part of url)
    :param current_user: a User
    :param remainder: remainder of url
    :param bool api: whether this is handling a /rest/ request or not

    :return: project (to be set as c.project)
    :return: remainder (possibly modified)
    """

    prefix = nbhd.shortname_prefix
    pname = unquote(name)
    provider = plugin.ProjectRegistrationProvider.get()
    try:
        provider.shortname_validator.to_python(pname, check_allowed=False, neighborhood=nbhd)
    except Invalid:
        project = None
    else:
        project = M.Project.query.get(shortname=prefix + pname, neighborhood_id=nbhd._id)
    if project is None and prefix == 'u/':
        # create user-project if it is missing
        user = M.User.query.get(username=pname, disabled=False, pending=False)
        if user:
            project = user.private_project()
            if project.shortname != prefix + pname:
                # might be different URL than the URL requested
                # e.g. if username isn't valid project name and user_project_shortname() converts the name
                new_url = project.url()
                if api:
                    new_url = '/rest' + new_url
                new_url += '/'.join(remainder)
                if request.query_string:
                    new_url += '?' + request.query_string
                redirect(new_url)
    if project is None:
        # look for neighborhood tools matching the URL
        project = nbhd.neighborhood_project
        return project, (pname,) + remainder  # include pname in new remainder, it is actually the nbhd tool path
    if project and prefix == 'u/':
        # make sure user-projects are associated with an enabled user
        user = project.user_project_of
        if not user or user.disabled or user.pending:
            raise exc.HTTPNotFound
    if project.database_configured is False:
        if remainder == ('user_icon',):
            redirect(g.forge_static('images/user.png'))
        elif current_user.username == pname:
            log.info('Configuring %s database for access to %r', pname, remainder)
            project.configure_project(is_user_project=True)
        else:
            raise exc.HTTPNotFound, pname
    if project is None or (project.deleted and not has_access(project, 'update')()):
        raise exc.HTTPNotFound, pname
    return project, remainder
コード例 #35
0
ファイル: app.py プロジェクト: apache/incubator-allura
    def admin_menu(self, force_options=False):
        """Return the admin menu for this Application.

        Default implementation will return a menu with up to 3 links:

            - 'Permissions', if the current user has admin access to the
                project in which this Application is installed
            - 'Options', if this Application has custom options, or
                ``force_options`` is True
            - 'Label', for editing this Application's label

        Subclasses should override this method to provide additional admin
        menu items.

        :param force_options: always include an 'Options' link in the menu,
            even if this Application has no custom options
        :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`

        """
        admin_url = c.project.url() + 'admin/' + \
            self.config.options.mount_point + '/'
        links = []
        if self.permissions and has_access(c.project, 'admin')():
            links.append(
                SitemapEntry('Permissions', admin_url + 'permissions'))
        if force_options or len(self.config_options) > 3:
            links.append(
                SitemapEntry('Options', admin_url + 'options', className='admin_modal'))
        links.append(
            SitemapEntry('Label', admin_url + 'edit_label', className='admin_modal'))
        return links
コード例 #36
0
 def handle_shortlink(self, lnk, sender, rcpt):
     art = lnk.ref.artifact
     if security.has_access(art, 'read', user=M.User.anonymous())():
         index = art.index()
         text = index['snippet_s'] or h.get_first(index, 'title')
         url = urljoin(tg.config['base_url'], index['url_s'])
         self.notice(rcpt, '[%s] - [%s](%s)' % (lnk.link, text, url))
コード例 #37
0
 def fork(self, project_id=None, mount_point=None, mount_label=None):
     # this shows the form and handles the submission
     security.require_authenticated()
     if not c.app.forkable: raise exc.HTTPNotFound
     from_repo = c.app.repo
     ThreadLocalORMSession.flush_all()
     ThreadLocalORMSession.close_all()
     from_project = c.project
     to_project = M.Project.query.get(_id=ObjectId(project_id))
     mount_label = mount_label or '%s - %s' % (c.project.name, c.app.config.options.mount_label)
     mount_point = (mount_point or from_project.shortname)
     if request.method != 'POST' or not mount_point:
         return dict(from_repo=from_repo,
                     user_project=c.user.private_project(),
                     mount_point=mount_point,
                     mount_label=mount_label)
     else:
         with h.push_config(c, project=to_project):
             if not to_project.database_configured:
                 to_project.configure_project(is_user_project=True)
             security.require(security.has_access(to_project, 'admin'))
             try:
                 to_project.install_app(
                     ep_name=from_repo.tool_name,
                     mount_point=mount_point,
                     mount_label=mount_label,
                     cloned_from_project_id=from_project._id,
                     cloned_from_repo_id=from_repo._id)
                 redirect(to_project.url()+mount_point+'/')
             except exc.HTTPRedirection:
                 raise
             except Exception, ex:
                 flash(str(ex), 'error')
                 redirect(request.referer)
コード例 #38
0
 def handle_shortlink(self, lnk, sender, rcpt):
     art = lnk.ref.artifact
     if security.has_access(art, 'read', user=M.User.anonymous())():
         index = art.index()
         text = index['snippet_s'] or h.get_first(index, 'title')
         url = urljoin(tg.config.get('base_url', 'http://sourceforge.net'), index['url_s'])
         self.notice(rcpt, '[%s] - [%s](%s)' % (lnk.link, text,url))
コード例 #39
0
    def search(self,
               q=None,
               history=None,
               project=None,
               limit=None,
               page=0,
               **kw):
        if project:
            redirect(c.project.url() + 'search?' +
                     urlencode(dict(q=q, history=history)))
        results = []
        count = 0
        limit, page, start = g.handle_paging(limit, page, default=25)
        if not q:
            q = ''
        else:
            query = [
                'is_history_b:%s' % history,
                'project_id_s:%s' % c.project._id,
                'mount_point_s:%s' % c.app.config.options.mount_point,
                'type_s:%s' % ShortUrl.type_s
            ]
            if not has_access(c.app, 'view_private'):
                query.append('private_b:False')
            results = search(q, fq=query)

            if results:
                count = results.hits
        c.search_results = W.search_results
        return dict(q=q,
                    history=history,
                    results=results or [],
                    count=count,
                    limit=limit,
                    page=page)
コード例 #40
0
 def admin_menu(self):
     admin_url = c.project.url() + 'admin/' + self.config.options.mount_point + '/'
     links = []
     if has_access(self, 'configure')():
         links.append(SitemapEntry('Forums', admin_url + 'forums'))
     links += super(ForgeDiscussionApp, self).admin_menu()
     return links
コード例 #41
0
 def post(self,
          text,
          message_id=None,
          parent_id=None,
          timestamp=None,
          ignore_security=False,
          **kw):
     if not ignore_security:
         require_access(self, 'post')
     if self.ref_id and self.artifact:
         self.artifact.subscribe()
     if message_id is None:
         message_id = h.gen_message_id()
     parent = parent_id and self.post_class().query.get(_id=parent_id)
     slug, full_slug = self.post_class().make_slugs(parent, timestamp)
     kwargs = dict(discussion_id=self.discussion_id,
                   full_slug=full_slug,
                   slug=slug,
                   thread_id=self._id,
                   parent_id=parent_id,
                   text=text,
                   status='pending')
     if timestamp is not None:
         kwargs['timestamp'] = timestamp
     if message_id is not None:
         kwargs['_id'] = message_id
     post = self.post_class()(**kwargs)
     if ignore_security or not self.is_spam(post) and has_access(
             self, 'unmoderated_post')():
         log.info('Auto-approving message from %s', c.user.username)
         file_info = kw.get('file_info', None)
         post.approve(file_info, notify=kw.get('notify', True))
     else:
         self.notify_moderators(post)
     return post
コード例 #42
0
ファイル: notification.py プロジェクト: brondsem/allura
 def send_direct(self, user_id):
     user = User.query.get(_id=ObjectId(user_id), disabled=False, pending=False)
     artifact = self.ref.artifact
     log.debug('Sending direct notification %s to user %s',
               self._id, user_id)
     # Don't send if user disabled
     if not user:
         log.debug("Skipping notification - enabled user %s not found" %
                   user_id)
         return
     # Don't send if user doesn't have read perms to the artifact
     if user and artifact and \
             not security.has_access(artifact, 'read', user)():
         log.debug("Skipping notification - User %s doesn't have read "
                   "access to artifact %s" % (user_id, str(self.ref_id)))
         log.debug("User roles [%s]; artifact ACL [%s]; PSC ACL [%s]",
                   ', '.join([str(r) for r in security.Credentials.get().user_roles(
                       user_id=user_id, project_id=artifact.project._id).reaching_ids]),
                   ', '.join([str(a) for a in artifact.acl]),
                   ', '.join([str(a) for a in artifact.parent_security_context().acl]))
         return
     allura.tasks.mail_tasks.sendmail.post(
         destinations=[str(user_id)],
         fromaddr=self.from_address,
         reply_to=self.reply_to_address,
         subject=self.subject,
         message_id=self._id,
         in_reply_to=self.in_reply_to,
         references=self.references,
         sender=self._sender(),
         metalink=h.absurl(self.link),
         text=(self.text or '') + self.footer())
コード例 #43
0
    def edit_label(self):
        """Renders form to update the Application's ``mount_label``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())
コード例 #44
0
ファイル: app.py プロジェクト: apache/incubator-allura
    def permissions(self):
        """Render the permissions management web page.

        """
        from ext.admin.widgets import PermissionCard, BlockUser, BlockList
        c.card = PermissionCard()
        c.block_user = BlockUser()
        c.block_list = BlockList()
        permissions = dict((p, []) for p in self.app.permissions)
        block_list = defaultdict(list)
        for ace in self.app.config.acl:
            if ace.access == model.ACE.ALLOW:
                try:
                    permissions[ace.permission].append(ace.role_id)
                except KeyError:
                    # old, unknown permission
                    pass
            elif ace.access == model.ACE.DENY:
                role = model.ProjectRole.query.get(_id=ace.role_id)
                if role.name is None and role.user:
                    block_list[ace.permission].append((role.user, ace.reason))
        return dict(
            app=self.app,
            allow_config=has_access(c.project, 'admin')(),
            permissions=permissions,
            block_list=block_list)
コード例 #45
0
    def options(self):
        """Renders form to update the Application's ``config.options``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())
コード例 #46
0
ファイル: app.py プロジェクト: apache/incubator-allura
    def options(self):
        """Renders form to update the Application's ``config.options``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())
コード例 #47
0
ファイル: auth.py プロジェクト: phraniiac/allura
    def _auth_repos(self, user):
        def _unix_group_name(neighborhood, shortname):
            path = neighborhood.url_prefix + \
                shortname[len(neighborhood.shortname_prefix):]
            parts = [p for p in path.split('/') if p]
            if len(parts) == 2 and parts[0] == 'p':
                parts = parts[1:]
            return '.'.join(reversed(parts))

        repos = []
        for p in user.my_projects():
            for p in [p] + p.direct_subprojects:
                for app in p.app_configs:
                    if not issubclass(g.entry_points["tool"][app.tool_name],
                                      RepositoryApp):
                        continue
                    if not has_access(app, 'write', user, p):
                        continue
                    repos.append(
                        '/%s/%s/%s' %
                        (app.tool_name.lower(),
                         _unix_group_name(p.neighborhood, p.shortname),
                         app.options['mount_point']))
        repos.sort()
        return repos
コード例 #48
0
ファイル: discuss.py プロジェクト: vclisunlang/allura
 def notify_moderators(self, post):
     ''' Notify moderators that a post needs approval [#2963] '''
     artifact = self.artifact or self
     subject = '[%s:%s] Moderation action required' % (
         c.project.shortname, c.app.config.options.mount_point)
     author = post.author()
     url = self.discussion_class().query.get(_id=self.discussion_id).url()
     text = ('The following submission requires approval at %s before '
             'it can be approved for posting:\n\n%s'
             % (h.absurl(url + 'moderate'), post.text))
     n = Notification(
         ref_id=artifact.index_id(),
         topic='message',
         link=artifact.url(),
         _id=artifact.url() + post._id,
         from_address=str(author._id) if author != User.anonymous()
         else None,
         reply_to_address=g.noreply,
         subject=subject,
         text=text,
         in_reply_to=post.parent_id,
         author_id=author._id,
         pubdate=datetime.utcnow())
     users = self.app_config.project.users()
     for u in users:
         if (has_access(self, 'moderate', u)
             and Mailbox.subscribed(user_id=u._id,
                                    app_config_id=post.app_config_id)):
                 n.send_direct(str(u._id))
コード例 #49
0
 def _lookup(self, pname, *remainder):
     pname = unquote(pname)
     if not h.re_path_portion.match(pname):
         raise exc.HTTPNotFound, pname
     project = M.Project.query.get(shortname=self.prefix + pname,
                                   neighborhood_id=self.neighborhood._id)
     if project is None:
         project = self.neighborhood.neighborhood_project
         c.project = project
         return ProjectController()._lookup(pname, *remainder)
     if project.database_configured == False:
         if remainder == ('user_icon', ):
             redirect(g.forge_static('images/user.png'))
         elif c.user.username == pname:
             log.info('Configuring %s database for access to %r', pname,
                      remainder)
             project.configure_project(is_user_project=True)
         else:
             raise exc.HTTPNotFound, pname
     c.project = project
     if project is None or (project.deleted
                            and not has_access(c.project, 'update')()):
         raise exc.HTTPNotFound, pname
     if project.neighborhood.name != self.neighborhood_name:
         redirect(project.url())
     return ProjectController(), remainder
コード例 #50
0
 def get_all(self, **kw):
     page_titles = []
     pages = WM.Page.query.find(dict(app_config_id=c.app.config._id, deleted=False))
     for page in pages:
         if has_access(page, 'read')():
             page_titles.append(page.title)
     return dict(pages=page_titles)
コード例 #51
0
ファイル: main.py プロジェクト: 99Kies/allura
 def exfeed(self):
     feeds_list = []
     for feed in self.app.external_feeds_list:
         feeds_list.append(feed)
     return dict(app=self.app,
                 feeds_list=feeds_list,
                 allow_config=has_access(self.app, 'configure')())
コード例 #52
0
    def permissions(self):
        """Render the permissions management web page.

        """
        from ext.admin.widgets import PermissionCard, BlockUser, BlockList
        c.card = PermissionCard()
        c.block_user = BlockUser()
        c.block_list = BlockList()
        permissions = dict((p, []) for p in self.app.permissions)
        block_list = defaultdict(list)
        for ace in self.app.config.acl:
            if ace.access == model.ACE.ALLOW:
                try:
                    permissions[ace.permission].append(ace.role_id)
                except KeyError:
                    # old, unknown permission
                    pass
            elif ace.access == model.ACE.DENY:
                role = model.ProjectRole.query.get(_id=ace.role_id)
                if role.name is None and role.user:
                    block_list[ace.permission].append((role.user, ace.reason))
        return dict(app=self.app,
                    allow_config=has_access(c.project, 'admin')(),
                    permissions=permissions,
                    block_list=block_list)
コード例 #53
0
ファイル: timeline.py プロジェクト: abhinavthomas/allura
 def has_activity_access(self, perm, user, activity):
     """Return True if user has perm access to this object, otherwise
     return False.
     """
     if self.project is None or getattr(self, 'deleted', False):
         return False
     return security.has_access(self, perm, user, self.project)
コード例 #54
0
 def send_direct(self, user_id):
     user = User.query.get(_id=ObjectId(user_id), disabled=False)
     artifact = self.ref.artifact
     log.debug('Sending direct notification %s to user %s', self._id, user_id)
     # Don't send if user disabled
     if not user:
         log.debug("Skipping notification - enabled user %s not found" % user_id)
         return
     # Don't send if user doesn't have read perms to the artifact
     if user and artifact and \
             not security.has_access(artifact, 'read', user)():
         log.debug("Skipping notification - User %s doesn't have read "
                   "access to artifact %s" % (user_id, str(self.ref_id)))
         log.debug("User roles [%s]; artifact ACL [%s]; PSC ACL [%s]",
                 ', '.join([str(r) for r in security.Credentials.get().user_roles(user_id=user_id, project_id=artifact.project._id).reaching_ids]),
                 ', '.join([str(a) for a in artifact.acl]),
                 ', '.join([str(a) for a in artifact.parent_security_context().acl]))
         return
     allura.tasks.mail_tasks.sendmail.post(
         destinations=[str(user_id)],
         fromaddr=self.from_address,
         reply_to=self.reply_to_address,
         subject=self.subject,
         message_id=self._id,
         in_reply_to=self.in_reply_to,
         sender=self._sender(),
         text=(self.text or '') + self.footer())
コード例 #55
0
    def admin_menu(self, force_options=False):
        """Return the admin menu for this Application.

        Default implementation will return a menu with up to 3 links:

            - 'Permissions', if the current user has admin access to the
                project in which this Application is installed
            - 'Options', if this Application has custom options, or
                ``force_options`` is True
            - 'Label', for editing this Application's label

        Subclasses should override this method to provide additional admin
        menu items.

        :param force_options: always include an 'Options' link in the menu,
            even if this Application has no custom options
        :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`

        """
        admin_url = c.project.url()+'admin/'+self.config.options.mount_point+'/'
        links = []
        if self.permissions and has_access(c.project, 'admin')():
            links.append(SitemapEntry('Permissions', admin_url + 'permissions'))
        if force_options or len(self.config_options) > 3:
            links.append(SitemapEntry('Options', admin_url + 'options', className='admin_modal'))
        links.append(SitemapEntry('Label', admin_url + 'edit_label', className='admin_modal'))
        return links