Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/onegov/org/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import transaction
from aiohttp import ClientTimeout
from markupsafe import Markup
from sqlalchemy.orm import object_session
from urlextract import URLExtract

Expand Down Expand Up @@ -89,16 +90,19 @@ def repl(matchobj: re.Match[str]) -> str:
value = getattr(item, field, None)
if not value:
continue
new_val = pattern.sub(repl, value)
if value != new_val:
count += 1
new_val, n = pattern.subn(repl, value)
if n:
count += n
id_count = count_by_id.setdefault(
group_by,
defaultdict(int)
)

id_count[field] += 1
id_count[field] += n
if not test:
new_val = (
Markup(new_val) # nosec: B704
if isinstance(value, Markup) else new_val)
setattr(
item,
field,
Expand Down
6 changes: 6 additions & 0 deletions src/onegov/org/models/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,9 @@ def page_by_index(self, index: int) -> Self:
page=index
)

def by_title(self, title: str) -> Topic | None:
return self.subset().filter(Topic.title == title).first()


class NewsCollection(Pagination[News], AdjacencyListCollection[News]):
"""
Expand Down Expand Up @@ -497,6 +500,9 @@ def __link_alias__(self) -> str:
}
)

def by_title(self, title: str) -> News | None:
return self.subset().filter(News.title == title).first()


class AtoZPages(AtoZ[Topic]):

Expand Down
7 changes: 0 additions & 7 deletions src/onegov/org/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,6 @@ def query_settings() -> Iterator[dict[str, Any]]:
for action, fn in q(request.app):
if 'setting' in action.predicates:
setting = copy(action.predicates)

# ogc-3003: for now we don't show the `Migration Links` in
# settings as it breaks html. Still directly accessible
# via `/migrate-links`
if setting['name'] == 'migrate-links':
continue

# exclude this setting view if it's disabled for the app
if (
setting['name'] == 'citizen-login-settings'
Expand Down
80 changes: 74 additions & 6 deletions tests/onegov/town6/test_views_settings.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from __future__ import annotations

from onegov.api.models import ApiKey
from xml.etree.ElementTree import tostring

import transaction
from onegov.api.models import ApiKey
from onegov.core.utils import Bunch
from onegov.org.models import News
from onegov.org.models import Topic
from onegov.org.models.page import TopicCollection, NewsCollection

from typing import TYPE_CHECKING, Any

from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .conftest import Client


def test_gever_settings_only_https_allowed(client: Client) -> None:

client.login_admin()
settings = client.get('/settings').click('Gever API')
settings.form['gever_username'] = 'foo'
Expand All @@ -30,7 +35,6 @@ def test_gever_settings_only_https_allowed(client: Client) -> None:


def test_api_keys_create_and_delete(client: Client) -> None:

client.login_admin()

settings = client.get('/api-keys')
Expand Down Expand Up @@ -121,9 +125,7 @@ def test_analytics_settings(client: Client) -> None:
) in settings



def test_firebase_settings(client: Client) -> None:

client.login_admin()

# Pretend this is real data (it's completely random)
Expand Down Expand Up @@ -165,3 +167,69 @@ def test_resource_settings(client: Client) -> None:
assert 'Allgemeine Informationen zu Reservationen' in page
assert '<h1>foo</h1>' in page
assert '<p>bar</p>' in page


def test_migrate_links(client: Client) -> None:
session = client.app.session()
request: Any = Bunch(**{
'session': session,
'identity.role': 'admin'
})
old_domain = 'foo.ch'

# create topic
topic = Topic(title='Foo Topic', name='foo-topic')
topic.text = '<p>Wow, https://foo.ch/abc is a great page!</p>'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
topic.text = '<p>Wow, https://foo.ch/abc is a great page!</p>'
topic.text = Markup('<p>Wow, https://foo.ch/abc is a great page!</p>')

Make sure to use Markup here, otherwise <p> will get escaped to &lt;p&gt;

session.add(topic)
topic_text = str(topic.text)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
topic_text = str(topic.text)
topic_text = topic.text
assert topic_text is not None

The type checker error was due to this potentially being None, not because it wasn't a str.


# add news article (must be under the seeded /news/ root)
from onegov.page import PageCollection
news_root = PageCollection(session).by_path('/news/', ensure_type='news')
assert isinstance(news_root, News)
news = News(title='Big News', name='big-news', parent=news_root)
news.text = ('<p>Big news https://foo.ch/big-news and bigger news'
'can be found here https://foo.ch/bigger-news</p>')
Comment on lines +191 to +192
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
news.text = ('<p>Big news https://foo.ch/big-news and bigger news'
'can be found here https://foo.ch/bigger-news</p>')
news.text = Markup('<p>Big news https://foo.ch/big-news and bigger news'
'can be found here https://foo.ch/bigger-news</p>')

session.add(news)
news_text = str(news.text)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
news_text = str(news.text)
news_text = news.text
assert news_text is not None


transaction.commit()

def get_topic_text() -> str:
t = TopicCollection(session).by_title('Foo Topic')
assert t is not None and t.text is not None
return str(t.text)

def get_news_text() -> str:
n = NewsCollection(request).by_title('Big News')
assert n is not None and n.text is not None
return str(n.text)
Comment on lines +198 to +206
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def get_topic_text() -> str:
t = TopicCollection(session).by_title('Foo Topic')
assert t is not None and t.text is not None
return str(t.text)
def get_news_text() -> str:
n = NewsCollection(request).by_title('Big News')
assert n is not None and n.text is not None
return str(n.text)
def get_topic_text() -> Markup:
t = TopicCollection(session).by_title('Foo Topic')
assert t is not None and t.text is not None
return t.text
def get_news_text() -> Markup:
n = NewsCollection(request).by_title('Big News')
assert n is not None and n.text is not None
return n.text


assert old_domain in get_topic_text()
assert old_domain in get_news_text()

# execute migrate links test
client.login_admin()
migrate_page = client.get('/migrate-links')
migrate_page.form['old_domain'] = old_domain
migrate_page.form['test'] = True
result = migrate_page.form.submit()
assert 'Total 3 Links gefunden' in result

assert old_domain in get_topic_text()
assert old_domain in get_news_text()

# execute migrate links
migrate_page = client.get('/migrate-links')
migrate_page.form['old_domain'] = old_domain
migrate_page.form['test'] = False
result = migrate_page.form.submit().follow()
assert '3 Links migriert' in result

topic_text_new = get_topic_text()
news_text_new = get_news_text()
assert old_domain not in topic_text_new
assert old_domain not in news_text_new

assert topic_text.replace('foo.ch', 'localhost') == topic_text_new
assert news_text.replace('foo.ch', 'localhost') == news_text_new
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should use an <a> tag in at least one of your tests, to make sure those remain intact as well, it should actually be very rare to encounter a naked link, they should almost always be part of an <a> tag in these fields.

Loading