Example #1
0
def app_ctx(cfg):
    namespace_mapping, backend_mapping, acl_mapping = create_simple_mapping(
        "stores:memory:",
        cfg.default_acl
    )
    more_config = dict(
        namespace_mapping=namespace_mapping,
        backend_mapping=backend_mapping,
        acl_mapping=acl_mapping,
        create_storage=True,  # create a fresh storage at each app start
        destroy_storage=True,  # kill all storage contents at app shutdown
        create_index=True,  # create a fresh index at each app start
        destroy_index=True,  # kill index contents at app shutdown
    )
    app = create_app_ext(
        flask_config_dict=dict(SECRET_KEY='foobarfoobar'),
        moin_config_class=cfg,
        **more_config
    )
    ctx = app.test_request_context('/', base_url="http://localhost:8080/")
    ctx.push()
    before_wiki()

    yield app, ctx

    teardown_wiki('')
    ctx.pop()
    destroy_app(app)
Example #2
0
    def run(self, query):
        before_wiki()
        if query:
            qp = app.storage.query_parser([
                NAME_EXACT,
            ])
            q = qp.parse(query_text)
        else:
            q = Every()

        for current_rev in app.storage.search(q, limit=None):
            current_name = current_rev.meta[NAME]
            current_revid = current_rev.meta[REVID]
            print "Destroying historical revisions of {0!r}:".format(
                current_name)
            has_historical_revision = False
            for rev in current_rev.item.iter_revs():
                revid = rev.meta[REVID]
                if revid == current_revid:
                    continue
                has_historical_revision = True
                name = rev.meta[NAME]
                if name == current_name:
                    print "    Destroying revision {0}".format(revid)
                else:
                    print "    Destroying revision {0} (named {1!r})".format(
                        revid, name)
                current_rev.item.destroy_revision(revid)
            if not has_historical_revision:
                print "    (no historical revisions)"

        print "Finished reducing backend."
Example #3
0
    def test_url_for_item(self):
        before_wiki()
        revid = 'cdc431e0fc624d6fb8372152dcb66457'

        tests = [(('SomePage', '', '', '', CURRENT, 'frontend.show_item', False), '/SomePage'),
                 # Method signature to understand the tuple parameters
                 # (item_name, wiki_name='', namespace='', rev=CURRENT, endpoint='frontend.show_item', _external=False):
                 (('SomePage', '', '', '', CURRENT, 'frontend.show_item', True), 'http://*****:*****@itemid/SomeItemID'),
                 (('SomePage', 'non-existent', '', 'ns1', CURRENT, 'frontend.show_item', False), '/non-existent/ns1/SomePage'),
                ]

        for (item_name, wiki_name, field, namespace, rev, endpoint, _external), url in tests:
            assert url_for_item(item_name, wiki_name, field, namespace, rev, endpoint, _external) == url
Example #4
0
    def run(self, name, uid):
        flags_given = name or uid
        if not flags_given:
            print 'incorrect number of arguments'
            import sys
            sys.exit()

        before_wiki()
        if uid:
            u = user.User(uid)
        elif name:
            u = user.User(auth_username=name)

        if not u.exists():
            print 'This user "{0!r}" does not exists!'.format(u.name)
            return

        print " {0:<20} {1!r:<25} {2:<35}".format(u.itemid, u.name, u.email),
        if not u.disabled:  # only disable once
            u.disabled = 1
            u.name = u"{0}-{1}".format(u.name, u.id)
            if u.email:
                u.email = u"{0}-{1}".format(u.email, u.id)
            u.subscriptions = []
            u.save()
            print "- disabled."
        else:
            print "- is already disabled."
Example #5
0
    def test_url_for_item(self):
        before_wiki()
        revid = 'cdc431e0fc624d6fb8372152dcb66457'

        tests = [(('SomePage', '', '', '', CURRENT, 'frontend.show_item', False), '/SomePage'),
                 # Method signature to understand the tuple parameters
                 # (item_name, wiki_name='', namespace='', rev=CURRENT, endpoint='frontend.show_item', _external=False):
                 (('SomePage', '', '', '', CURRENT, 'frontend.show_item', True), 'http://*****:*****@itemid/SomeItemID'),
                 (('SomePage', 'non-existent', '', 'ns1', CURRENT, 'frontend.show_item', False), '/non-existent/ns1/SomePage'),
                ]

        for (item_name, wiki_name, field, namespace, rev, endpoint, _external), url in tests:
            assert url_for_item(item_name, wiki_name, field, namespace, rev, endpoint, _external) == url
Example #6
0
    def run(self, query):
        before_wiki()
        if query:
            qp = app.storage.query_parser([NAME_EXACT, ])
            q = qp.parse(query_text)
        else:
            q = Every()

        for current_rev in app.storage.search(q, limit=None):
            current_name = current_rev.meta[NAME]
            current_revid = current_rev.meta[REVID]
            print "Destroying historical revisions of {0!r}:".format(current_name)
            has_historical_revision = False
            for rev in current_rev.item.iter_revs():
                revid = rev.meta[REVID]
                if revid == current_revid:
                    continue
                has_historical_revision = True
                name = rev.meta[NAME]
                if name == current_name:
                    print "    Destroying revision {0}".format(revid)
                else:
                    print "    Destroying revision {0} (named {1!r})".format(revid, name)
                current_rev.item.destroy_revision(revid)
            if not has_historical_revision:
                print "    (no historical revisions)"

        print "Finished reducing backend."
Example #7
0
    def run(self, name, uid):
        flags_given = name or uid
        if not flags_given:
            print 'incorrect number of arguments'
            import sys
            sys.exit()

        before_wiki()
        if uid:
            u = user.User(uid)
        elif name:
            u = user.User(auth_username=name)

        if not u.exists():
            print 'This user "{0!r}" does not exists!'.format(u.name)
            return

        print " {0:<20} {1!r:<25} {2:<35}".format(u.itemid, u.name, u.email),
        if not u.disabled:  # only disable once
            u.disabled = 1
            u.name = u"{0}-{1}".format(u.name, u.id)
            if u.email:
                u.email = u"{0}-{1}".format(u.email, u.id)
            u.subscriptions = []
            u.save()
            print "- disabled."
        else:
            print "- is already disabled."
Example #8
0
    def run(self, name, display_name, email, openid, password):
        before_wiki()
        msg = user.create_user(username=name,
                               password=password,
                               email=email,
                               openid=openid)

        if msg:
            print msg
        else:
            u = user.User(auth_username=name)
            print " %-20s %-25s %-35s - created." % (u.itemid, u.name, u.email),
Example #9
0
    def run(self, name, uid, password, all_users, notify, verbose, subject,
            text, text_file, skip_invalid):
        flags_given = name or uid or all_users
        if not flags_given:
            print 'incorrect number of arguments'
            sys.exit(1)

        if notify and not app.cfg.mail_enabled:
            print "This wiki is not enabled for mail processing. The --notify option requires this. Aborting..."
            sys.exit(1)

        if text_file:
            with open(text_file) as f:
                text = f.read().decode('utf-8')

        before_wiki()
        if uid:
            query = {ITEMID: uid}
        elif name:
            query = {NAME_EXACT: name}
        elif all_users:
            query = {}

        # sorting the list so we have some specific, reproducable order
        uids_metas = sorted([(rev.meta[ITEMID], rev.meta)
                             for rev in user.search_users(**query)])
        total = len(uids_metas)
        for nr, (uid, meta) in enumerate(uids_metas, start=1):
            name = meta[NAME]
            email = meta.get(EMAIL)
            if email is None:
                email = meta.get(EMAIL_UNVALIDATED)
                if email is None:
                    raise ValueError(
                        "neither EMAIL nor EMAIL_UNVALIDATED key is present in user profile metadata of uid %r name %r"
                        % (uid, name))
                else:
                    email += '[email_unvalidated]'
            try:
                set_password(uid,
                             password,
                             notify=notify,
                             skip_invalid=skip_invalid,
                             subject=subject,
                             text=text)
            except Fault as err:
                status = "FAILURE: [%s]" % str(err)
            else:
                status = "SUCCESS"
            if verbose:
                print "uid %s, name %s, email %s (%05d / %05d) %s" % (
                    uid, name, email, nr, total, status)
Example #10
0
    def run(self, name, display_name, email, openid, password):
        before_wiki()
        msg = user.create_user(username=name,
                               password=password,
                               email=email,
                               openid=openid)

        if msg:
            print msg
        else:
            u = user.User(auth_username=name)
            print " %-20s %-25s %-35s - created." % (u.itemid, u.name,
                                                     u.email),
Example #11
0
def init_test_app(given_config):
    namespace_mapping, router_index_uri = create_simple_mapping(
        "memory:", given_config.content_acl)
    more_config = dict(
        namespace_mapping=namespace_mapping,
        router_index_uri=router_index_uri,
    )
    app = create_app_ext(flask_config_dict=dict(SECRET_KEY='foobarfoobar'),
                         moin_config_class=given_config,
                         **more_config)
    ctx = app.test_request_context('/')
    ctx.push()
    before_wiki()
    return app, ctx
Example #12
0
    def run(self, query):
        before_wiki()
        if query:
            q = And([
                Term(WIKINAME, app.cfg.interwikiname),
                Regex(NAME_EXACT, query)
            ])
        else:
            q = Every()

        for current_rev in app.storage.search(q, limit=None):
            current_name = current_rev.meta[NAME]
            current_revid = current_rev.meta[REVID]
            print "Destroying historical revisions of {0!r}:".format(
                current_name)
            has_historical_revision = False
            for rev in current_rev.item.iter_revs():
                revid = rev.meta[REVID]
                if revid == current_revid:
                    # fixup metadata and overwrite existing revision; modified time will be updated if changed
                    changed = False
                    meta = dict(rev.meta)
                    if REV_NUMBER in meta and meta[
                            REV_NUMBER] > 1 or REV_NUMBER not in meta:
                        changed = True
                        meta[REV_NUMBER] = 1
                    if PARENTID in meta:
                        changed = True
                        del meta[PARENTID]
                    if changed:
                        current_rev.item.store_revision(meta,
                                                        current_rev.data,
                                                        overwrite=True)
                        print "    (current rev meta data updated)"
                    continue
                has_historical_revision = True
                name = rev.meta[NAME]
                if name == current_name:
                    print "    Destroying revision {0}".format(revid)
                else:
                    print "    Destroying revision {0} (named {1!r})".format(
                        revid, name)
                current_rev.item.destroy_revision(revid)
            if not has_historical_revision:
                print "    (no historical revisions)"

        print "Finished reducing backend."
Example #13
0
def init_test_app(given_config):
    namespace_mapping, acl_mapping = create_simple_mapping("stores:memory:", given_config.content_acl)
    more_config = dict(
        namespace_mapping=namespace_mapping,
        acl_mapping=acl_mapping,
        create_storage=True, # create a fresh storage at each app start
        destroy_storage=True, # kill all storage contents at app shutdown
        create_index=True, # create a fresh index at each app start
        destroy_index=True, # kill index contents at app shutdown
    )
    app = create_app_ext(flask_config_dict=dict(SECRET_KEY='foobarfoobar'),
                         moin_config_class=given_config,
                         **more_config)
    ctx = app.test_request_context('/', base_url="http://localhost:8080/")
    ctx.push()
    before_wiki()
    return app, ctx
Example #14
0
    def run(self, name, uid, password, all_users, notify, verbose, subject, text, text_file, skip_invalid):
        flags_given = name or uid or all_users
        if not flags_given:
            print 'incorrect number of arguments'
            sys.exit(1)

        if notify and not app.cfg.mail_enabled:
            print "This wiki is not enabled for mail processing. The --notify option requires this. Aborting..."
            sys.exit(1)

        if text_file:
            with open(text_file) as f:
                text = f.read().decode('utf-8')

        before_wiki()
        if uid:
            query = {ITEMID: uid}
        elif name:
            query = {NAME_EXACT: name}
        elif all_users:
            query = {}

        # sorting the list so we have some specific, reproducable order
        uids_metas = sorted([(rev.meta[ITEMID], rev.meta) for rev in user.search_users(**query)])
        total = len(uids_metas)
        for nr, (uid, meta) in enumerate(uids_metas, start=1):
            name = meta[NAME]
            email = meta.get(EMAIL)
            if email is None:
                email = meta.get(EMAIL_UNVALIDATED)
                if email is None:
                    raise ValueError("neither EMAIL nor EMAIL_UNVALIDATED key is present in user profile metadata of uid %r name %r" % (uid, name))
                else:
                    email += '[email_unvalidated]'
            try:
                set_password(uid, password, notify=notify, skip_invalid=skip_invalid,
                             subject=subject, text=text)
            except Fault as err:
                status = "FAILURE: [%s]" % str(err)
            else:
                status = "SUCCESS"
            if verbose:
                print "uid %s, name %s, email %s (%05d / %05d) %s" % (uid, name, email, nr, total, status)
Example #15
0
def app_ctx(cfg):
    namespace_mapping, backend_mapping, acl_mapping = create_simple_mapping(
        "stores:memory:", cfg.default_acl)
    more_config = dict(
        namespace_mapping=namespace_mapping,
        backend_mapping=backend_mapping,
        acl_mapping=acl_mapping,
        create_storage=True,  # create a fresh storage at each app start
        destroy_storage=True,  # kill all storage contents at app shutdown
        create_index=True,  # create a fresh index at each app start
        destroy_index=True,  # kill index contents at app shutdown
    )
    app = create_app_ext(flask_config_dict=dict(SECRET_KEY='foobarfoobar'),
                         moin_config_class=cfg,
                         **more_config)
    ctx = app.test_request_context('/', base_url="http://localhost:8080/")
    ctx.push()
    before_wiki()

    yield app, ctx

    teardown_wiki('')
    ctx.pop()
    destroy_app(app)
Example #16
0
    def run(self,
            directory='HTML',
            theme='topside_cms',
            exclude_ns='userprofiles',
            user=None,
            query=None):
        if theme:
            app.cfg.user_defaults[THEME_NAME] = theme
        exclude_ns = exclude_ns.split(',') if exclude_ns else []

        before_wiki()

        norm = os.path.normpath
        join = os.path.join

        if '/' in directory:
            # user has specified complete path to root
            html_root = directory
        else:
            html_root = norm(join(app.cfg.wikiconfig_dir, directory))
        repo_root = norm(join(app.cfg.wikiconfig_dir))
        moinmoin = norm(join(app.cfg.wikiconfig_dir, 'MoinMoin'))

        # override ACLs with permission to read all items
        for namespace, acls in app.cfg.acl_mapping:
            acls['before'] = 'All:read'

        # create an empty output directory after deleting any existing directory
        print u'Creating output directory {0}, starting to copy supporting files'.format(
            html_root)
        if os.path.exists(html_root):
            shutil.rmtree(html_root, ignore_errors=False)
        else:
            os.makedirs(html_root)

        # create subdirectories and copy static css, icons, images into "static" subdirectory
        shutil.copytree(norm(join(moinmoin, 'static')),
                        norm(join(html_root, 'static')))
        shutil.copytree(norm(join(repo_root, 'wiki_local')),
                        norm(join(html_root, '+serve/wiki_local')))

        # copy files from xstatic packaging into "+serve" subdirectory
        pkg = Config.pkg
        xstatic_dirs = [
            'font_awesome', 'jquery', 'jquery_tablesorter', 'autosize'
        ]
        if theme in [
                'basic',
        ]:
            xstatic_dirs.append('bootstrap')
        for dirs in xstatic_dirs:
            xs = XStatic(getattr(pkg, dirs),
                         root_url='/static',
                         provider='local',
                         protocol='http')
            shutil.copytree(xs.base_dir, norm(join(html_root, '+serve', dirs)))

        # copy directories for theme's static files
        theme = app.cfg.user_defaults[THEME_NAME]
        if theme == 'topside_cms':
            # topside_cms uses topside CSS files
            from_dir = norm(join(moinmoin, 'themes/topside/static'))
        else:
            from_dir = norm(join(moinmoin, 'themes', theme, 'static'))
        to_dir = norm(join(html_root, '_themes', theme))
        shutil.copytree(from_dir, to_dir)

        # convert: <img alt="svg" src="/+get/+7cb364b8ca5d4b7e960a4927c99a2912/svg" />
        # to:      <img alt="svg" src="+get/svg" />
        invalid_src = re.compile(r' src="/\+get/\+[0-9a-f]{32}/')
        valid_src = u' src="+get/'

        # get ready to render and copy individual items
        names = []
        home_page = None
        get_dir = norm(join(
            html_root, '+get'))  # images and other raw data from wiki content
        os.makedirs(get_dir)

        if query:
            q = And([
                Term(WIKINAME, app.cfg.interwikiname),
                Regex(NAME_EXACT, query)
            ])
        else:
            q = Every()

        print 'Starting to dump items'
        for current_rev in app.storage.search(q, limit=None, sortedby="name"):
            if current_rev.namespace in exclude_ns:
                # we usually do not copy userprofiles, no one can login to a static wiki
                continue
            if not current_rev.name:
                # TODO: we skip nameless tickets, but named tickets and comments are processed with ugly names
                continue

            try:
                item_name = current_rev.fqname.fullname
                rendered = show_item(
                    item_name, CURRENT)  # @@@  userid is needed for acls here
                # convert / characters in sub-items and namespaces and save names for index
                file_name = item_name.replace('/', SLASH)
                filename = norm(join(html_root, file_name))
                names.append(file_name)
            except Forbidden:
                print u'Failed to dump {0}: Forbidden'.format(current_rev.name)
                continue
            except KeyError:
                print u'Failed to dump {0}: KeyError'.format(current_rev.name)
                continue

            if not isinstance(rendered, unicode):
                print u'Rendering failed for {0} with response {1}'.format(
                    file_name, rendered)
                continue
            # make hrefs relative to current folder
            rendered = rendered.replace('href="/', 'href="')
            rendered = rendered.replace('src="/static/', 'src="static/')
            rendered = rendered.replace('src="/+serve/', 'src="+serve/')
            rendered = rendered.replace(
                'href="+index/"',
                'href="+index"')  # trailing slash changes relative position
            rendered = rendered.replace(
                '<a href="">', u'<a href="{0}">'.format(
                    app.cfg.default_root))  # TODO: fix basic theme
            # remove item ID from: src="/+get/+7cb364b8ca5d4b7e960a4927c99a2912/svg"
            rendered = re.sub(invalid_src, valid_src, rendered)
            rendered = self.subitems(rendered)

            # copy raw data for all items to output /+get directory; images are required, text items are of marginal/no benefit
            item = app.storage[current_rev.name]
            rev = item[CURRENT]
            with open(get_dir + '/' + file_name, 'wb') as f:
                shutil.copyfileobj(rev.data, f)

            # save rendered items or raw data to dump directory root
            contenttype = item.meta['contenttype'].split(';')[0]
            if contenttype in CONTENTTYPE_MEDIA and filename.endswith(
                    CONTENTTYPE_MEDIA_SUFFIX):
                # do not put a rendered html-formatted file with a name like video.mp4 into root; browsers want raw data
                with open(filename, 'wb') as f:
                    rev.data.seek(0)
                    shutil.copyfileobj(rev.data, f)
                    print u'Saved file named {0} as raw data'.format(
                        filename).encode('utf-8')
            else:
                with open(filename, 'wb') as f:
                    f.write(rendered.encode('utf8'))
                    print u'Saved file named {0}'.format(filename).encode(
                        'utf-8')

            if current_rev.name == app.cfg.default_root:
                # make duplicates of home page that are easy to find in directory list and open with a click
                for target in [(current_rev.name + '.html'),
                               ('_' + current_rev.name + '.html')]:
                    with open(norm(join(html_root, target)), 'wb') as f:
                        f.write(rendered.encode('utf8'))
                home_page = rendered  # save a copy for creation of index page

        if home_page:
            # create an index page by replacing the content of the home page with a list of items
            # work around differences in basic and modernized theme layout
            # TODO: this is likely to break as new themes are added
            if theme == 'basic':
                start = '<div class="moin-content" role="main">'  # basic
                end = '<footer class="navbar moin-footer">'
                div_end = '</div>'
            else:
                start = '<div id="moin-content">'  # modernized , topside, topside cms
                end = '<footer id="moin-footer">'
                div_end = '</div></div>'
            # build a page named "+index" containing links to all wiki items
            ul = u'<h1>Index</h1><ul>{0}</ul>'
            li = u'<li><a href="{0}">{1}</a></li>'
            links = []
            names.sort()
            for name in names:
                links.append(li.format(name, name.replace(SLASH, '/')))
            name_links = ul.format(u'\n'.join(links))
            try:
                part1 = home_page.split(start)[0]
                part2 = home_page.split(end)[1]
                page = part1 + start + name_links + div_end + end + part2
            except IndexError:
                page = home_page
                print u'Error: failed to find {0} in item named {1}'.format(
                    end, app.cfg.default_root)
            for target in ['+index', '_+index.html']:
                with open(norm(join(html_root, target)), 'wb') as f:
                    f.write(page.encode('utf8'))
        else:
            print 'Error: no item matching name in app.cfg.default_root was found'
Example #17
0
 def make_context():
     before_wiki()
     return dict(app=app, flaskg=flaskg)
Example #18
0
 def make_context():
     before_wiki()
     return dict(app=app, flaskg=flaskg)