Skip to content

Commit 27c3e25

Browse files
authored
Org: Avoid generating redundant file links for linked general files
This also updates WebTest to the newest version, since we need it in order to test multi-file uploads. TYPE: Bugfix LINK: OGC-1967
1 parent 01eb7d8 commit 27c3e25

21 files changed

+130
-44
lines changed

Diff for: setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ install_requires =
162162
webcolors
163163
webob
164164
websockets
165-
webtest < 3.0.1
165+
webtest
166166
werkzeug
167167
wtforms
168168
xlrd

Diff for: src/onegov/form/fields.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ def populate_obj(self, obj: object, name: str) -> None:
453453
dummy = _DummyFile()
454454
dummy.file = file
455455
field.populate_obj(dummy, 'file')
456-
if dummy.file is not None:
456+
# avoid generating multiple links to the same file
457+
if dummy.file is not None and dummy.file not in output:
457458
output.append(dummy.file)
458459
if (
459460
dummy.file is not file

Diff for: src/onegov/org/upgrade.py

+38
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,41 @@ def remove_stored_contact_html_and_opening_hours_html(
389389

390390
if 'contact_html' in obj.content:
391391
del obj.content['contact_html']
392+
393+
394+
@upgrade_task('Remove redundant page to general file links')
395+
def remove_redundant_page_to_general_file_links(
396+
context: UpgradeContext
397+
) -> None:
398+
399+
if not context.has_table('files_for_pages_files'):
400+
return
401+
402+
duplicate_pairs = [
403+
{'file_id': file_id, 'pages_id': pages_id}
404+
for file_id, pages_id in context.session.execute("""
405+
SELECT file_id, pages_id FROM (
406+
SELECT COUNT(*) as cnt, file_id, pages_id
407+
FROM files_for_pages_files
408+
GROUP BY file_id, pages_id
409+
) AS t
410+
WHERE t.cnt > 1
411+
""")
412+
]
413+
414+
if not duplicate_pairs:
415+
return
416+
417+
# delete all the links with duplicate entries
418+
context.session.execute("""
419+
DELETE
420+
FROM files_for_pages_files
421+
WHERE file_id = :file_id
422+
AND pages_id = :pages_id
423+
""", duplicate_pairs)
424+
425+
# then reinsert a single link per duplicate entry
426+
context.session.execute("""
427+
INSERT INTO files_for_pages_files (file_id, pages_id)
428+
VALUES (:file_id, :pages_id)
429+
""", duplicate_pairs)

Diff for: tests/onegov/feriennet/test_views.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2380,7 +2380,7 @@ def test_send_email_with_link_and_attachment(client, scenario):
23802380
client.login_admin()
23812381

23822382
page = client.get('/files')
2383-
page.form['file'] = Upload('Test.txt', b'File content.')
2383+
page.form['file'] = [Upload('Test.txt', b'File content.')]
23842384
page.form.submit()
23852385

23862386
file_id = FileCollection(scenario.session).query().one().id

Diff for: tests/onegov/gazette/test_views_notice_attachments.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,23 @@ def test_view_notice_attachments(gazette_app, temporary_path, pdf_1, pdf_2):
3535
assert "Keine Anhänge." in manage
3636

3737
# Try to upload an invalid file
38-
manage.form['file'] = Upload(
38+
manage.form['file'] = [Upload(
3939
'fake.pdf', 'PDF'.encode('utf-8'), 'application/pdf'
40-
)
40+
)]
4141
manage.form.submit(status=415)
4242

4343
# Upload two attachment (with the same name!)
4444
with open(pdf_1, 'rb') as file:
4545
content_1 = file.read()
46-
manage.form['file'] = Upload('1.pdf', content_1, 'application/pdf')
46+
manage.form['file'] = [Upload('1.pdf', content_1, 'application/pdf')]
4747
manage = manage.form.submit().maybe_follow()
4848
assert "Anhang hinzugefügt" in manage
4949
assert "1.pdf" in manage
5050
assert manage.click('1.pdf').content_type == 'application/pdf'
5151

5252
with open(pdf_2, 'rb') as file:
5353
content_2 = file.read()
54-
manage.form['file'] = Upload('1.pdf', content_2, 'application/pdf')
54+
manage.form['file'] = [Upload('1.pdf', content_2, 'application/pdf')]
5555
manage = manage.form.submit().maybe_follow()
5656
assert "Anhang hinzugefügt" in manage
5757
assert "1.pdf" in manage

Diff for: tests/onegov/org/test_extensions.py

+49-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
from markupsafe import Markup
88
from tempfile import TemporaryDirectory
99
from uuid import UUID
10+
from webtest import Upload
1011

1112
from onegov.core.orm.abstract import MoveDirection
1213
from onegov.core.utils import Bunch
1314
from onegov.form import Form
1415
from onegov.form.extensions import Extendable
16+
from onegov.org.models import Topic
1517
from onegov.org.models.extensions import (
1618
PersonLinkExtension, ContactExtension, AccessExtension, HoneyPotExtension,
1719
SidebarLinksExtension, PeopleShownOnMainPageExtension,
@@ -557,9 +559,8 @@ def test_general_file_link_extension(client):
557559
"*Experts say it's the fact that Govikon does not really exist.*"
558560
)
559561
filename = os.path.join(td, 'simple.pdf')
560-
pdf = create_pdf(filename)
561-
new_page.form.fields['files'][-1].value = [filename]
562-
new_page.files = pdf
562+
create_pdf(filename)
563+
new_page.form.fields['files'][-1].value = [Upload(filename)]
563564
new_page.form['show_file_links_in_sidebar'] = True
564565
page = new_page.form.submit().follow()
565566

@@ -576,6 +577,51 @@ def test_general_file_link_extension(client):
576577
assert 'simple.pdf' not in page
577578

578579

580+
def test_general_file_link_extension_deduplication(client):
581+
client.login_admin()
582+
583+
with TemporaryDirectory() as td:
584+
585+
root_page = client.get('/topics/themen')
586+
new_page = root_page.click('Thema')
587+
588+
assert 'files' in new_page.form.fields
589+
590+
new_page.form['title'] = "Living in Govikon is Swell"
591+
new_page.form['text'] = (
592+
"## Living in Govikon is Really Great\n"
593+
"*Experts say it's the fact that Govikon does not really exist.*"
594+
)
595+
filename = os.path.join(td, 'simple.pdf')
596+
create_pdf(filename)
597+
new_page.form.fields['files'][-1].value = [
598+
Upload(filename),
599+
Upload(filename)
600+
]
601+
new_page.form['show_file_links_in_sidebar'] = True
602+
page = new_page.form.submit().follow()
603+
604+
assert 'Living in Govikon is Swell' in page
605+
assert 'Dokumente' in page
606+
assert 'simple.pdf' in page
607+
608+
session = client.app.session()
609+
topic = session.query(Topic).filter(
610+
Topic.title == "Living in Govikon is Swell").one()
611+
assert len(topic.files) == 1
612+
613+
pages_id = topic.id
614+
file_id = topic.files[0].id
615+
616+
count, = session.execute("""
617+
SELECT COUNT(*)
618+
FROM files_for_pages_files
619+
WHERE pages_id = :pages_id
620+
AND file_id = :file_id
621+
""", {'pages_id': pages_id, 'file_id': file_id}).fetchone()
622+
assert count == 1
623+
624+
579625
def test_sidebar_links_extension(session):
580626

581627
class Topic(SidebarLinksExtension):

Diff for: tests/onegov/org/test_views_directory.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ def test_directory_explicitly_link_referenced_files(client):
848848
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
849849
with open(path, 'rb') as f:
850850
page = client.get('/files')
851-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
851+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
852852
page.form.submit()
853853

854854
pdf_url = (

Diff for: tests/onegov/org/test_views_event.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,8 @@ def test_view_occurrences_event_documents(client):
251251
client.login_admin()
252252
settings = client.get('/event-settings')
253253
filename_1 = os.path.join(td, 'zoo-programm-saison-2024.pdf')
254-
pdf_1 = create_pdf(filename_1)
255-
settings.form.fields['event_files'][-1].value = [filename_1]
256-
settings.files = [pdf_1]
254+
create_pdf(filename_1)
255+
settings.form.fields['event_files'][-1].value = [Upload(filename_1)]
257256
settings = settings.form.submit().follow()
258257
assert settings.status_code == 200
259258

Diff for: tests/onegov/org/test_views_files.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def test_view_files(client):
1010

1111
assert "Noch keine Dateien hochgeladen" in files_page
1212

13-
files_page.form['file'] = Upload('Test.txt', b'File content.')
13+
files_page.form['file'] = [Upload('Test.txt', b'File content.')]
1414
files_page.form.submit()
1515

1616
files_page = client.get('/files')

Diff for: tests/onegov/org/test_views_forms.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ def test_forms_explicitly_link_referenced_files(client):
367367
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
368368
with open(path, 'rb') as f:
369369
page = admin.get('/files')
370-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
370+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
371371
page.form.submit()
372372

373373
pdf_url = (

Diff for: tests/onegov/org/test_views_images.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ def test_view_images(client):
1212

1313
assert "Noch keine Bilder hochgeladen" in images_page
1414

15-
images_page.form['file'] = Upload('Test.txt', b'File content')
15+
images_page.form['file'] = [Upload('Test.txt', b'File content')]
1616
assert images_page.form.submit(expect_errors=True).status_code == 415
1717

18-
images_page.form['file'] = Upload('Test.jpg', create_image().read())
18+
images_page.form['file'] = [Upload('Test.jpg', create_image().read())]
1919
images_page.form.submit()
2020

2121
images_page = client.get('/images')

Diff for: tests/onegov/org/test_views_pages.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_pages(client):
7979
admin.login_admin()
8080

8181
images = admin.get('/images')
82-
images.form['file'] = Upload('Test.jpg', create_image().read())
82+
images.form['file'] = [Upload('Test.jpg', create_image().read())]
8383
images.form.submit()
8484
img_url = admin.get('/images').pyquery('.image-box a').attr('href')
8585

@@ -147,7 +147,7 @@ def test_pages_explicitly_link_referenced_files(client):
147147
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
148148
with open(path, 'rb') as f:
149149
page = admin.get('/files')
150-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
150+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
151151
page.form.submit()
152152

153153
pdf_url = (
@@ -200,7 +200,7 @@ def test_pages_person_link_extension(client):
200200
admin.login_admin()
201201

202202
images = admin.get('/images')
203-
images.form['file'] = Upload('Test.jpg', create_image().read())
203+
images.form['file'] = [Upload('Test.jpg', create_image().read())]
204204
images.form.submit()
205205
img_url = admin.get('/images').pyquery('.image-box a').attr('href')
206206

@@ -262,7 +262,7 @@ def test_delete_pages(client):
262262
)
263263
# we add a file attachment to ensure we can delete a page, even if
264264
# it contains file attachments
265-
new_page.form.fields['files'][-1] = Upload('test.txt')
265+
new_page.form.fields['files'][-1] = [Upload('test.txt')]
266266
page = new_page.form.submit().follow()
267267
delete_link = page.pyquery('a[ic-delete-from]')[0].attrib['ic-delete-from']
268268

Diff for: tests/onegov/org/test_views_photoalbum.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_manage_album(client):
2323
assert "noch keine Bilder" in album
2424

2525
images = albums.click("Bilder verwalten")
26-
images.form['file'] = Upload('test.jpg', create_image().read())
26+
images.form['file'] = [Upload('test.jpg', create_image().read())]
2727
images.form.submit()
2828

2929
select = album.click("Bilder auswählen")

Diff for: tests/onegov/org/test_views_resources.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def test_resources_explicitly_link_referenced_files(client):
156156
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
157157
with open(path, 'rb') as f:
158158
page = admin.get('/files')
159-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
159+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
160160
page.form.submit()
161161

162162
pdf_url = (

Diff for: tests/onegov/org/test_views_search.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def test_search_publication_files(client_with_es):
201201
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
202202
with open(path, 'rb') as f:
203203
page = client.get('/files')
204-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
204+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
205205
page.form.submit()
206206

207207
client.app.es_indexer.process()

Diff for: tests/onegov/org/test_views_signing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_sign_document(client):
1717
path = module_path('tests.onegov.org', 'fixtures/sample.pdf')
1818
with open(path, 'rb') as f:
1919
page = client.get('/files')
20-
page.form['file'] = Upload('Sample.pdf', f.read(), 'application/pdf')
20+
page.form['file'] = [Upload('Sample.pdf', f.read(), 'application/pdf')]
2121
page.form.submit()
2222

2323
pdf = FileCollection(client.app.session()).query().one()

Diff for: tests/onegov/swissvotes/test_views_page.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ def test_view_page_attachments(swissvotes_app, page_attachments):
6969
assert "No attachments." in manage
7070

7171
# Upload two attachment (en_US, de_CH)
72-
manage.form['file'] = Upload(
72+
manage.form['file'] = [Upload(
7373
'1.pdf',
7474
page_attachments['en_US']['CODEBOOK'].reference.file.read(),
7575
'application/pdf'
76-
)
76+
)]
7777
manage = manage.form.submit().maybe_follow()
7878
assert manage.status_code == 200
7979

@@ -84,11 +84,11 @@ def test_view_page_attachments(swissvotes_app, page_attachments):
8484
client.get('/locale/de_CH').follow()
8585
manage = client.get('/page/about').click("Anhänge verwalten")
8686

87-
manage.form['file'] = Upload(
87+
manage.form['file'] = [Upload(
8888
'2.pdf',
8989
page_attachments['de_CH']['CODEBOOK'].reference.file.read(),
9090
'application/pdf'
91-
)
91+
)]
9292
manage = manage.form.submit().maybe_follow()
9393
assert manage.status_code == 200
9494

@@ -162,11 +162,11 @@ def test_view_page_slider_images(swissvotes_app, slider_images):
162162
assert 'No attachments.' in manage
163163

164164
# Upload image
165-
manage.form['file'] = Upload(
165+
manage.form['file'] = [Upload(
166166
'2.1-x.png',
167167
slider_images['2.1-x'].reference.file.read(),
168168
'image/png'
169-
)
169+
)]
170170
assert manage.form.submit().maybe_follow().status_code == 200
171171

172172
manage = client.get('/page/about').click('Manage slider images')

Diff for: tests/onegov/town6/test_views_event.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from onegov.event import Event
1010
from tests.onegov.town6.common import step_class
1111
from unittest.mock import patch
12+
from webtest import Upload
1213

1314
from tests.shared.utils import create_pdf
1415

@@ -282,9 +283,8 @@ def test_view_occurrences_event_documents(client):
282283
client.login_admin()
283284
settings = client.get('/event-settings')
284285
filename_1 = os.path.join(td, 'zoo-programm-saison-2024.pdf')
285-
pdf_1 = create_pdf(filename_1)
286-
settings.form.fields['event_files'][-1].value = [filename_1]
287-
settings.files = [pdf_1]
286+
create_pdf(filename_1)
287+
settings.form.fields['event_files'][-1].value = [Upload(filename_1)]
288288
settings = settings.form.submit().follow()
289289
assert settings.status_code == 200
290290

Diff for: tests/onegov/town6/test_views_images.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ def test_view_images(client):
1212

1313
assert "Noch keine Bilder hochgeladen" in images_page
1414

15-
images_page.form['file'] = Upload('Test.txt', b'File content')
15+
images_page.form['file'] = [Upload('Test.txt', b'File content')]
1616
assert images_page.form.submit(expect_errors=True).status_code == 415
1717

18-
images_page.form['file'] = Upload('Test.jpg', create_image().read())
18+
images_page.form['file'] = [Upload('Test.jpg', create_image().read())]
1919
images_page.form.submit()
2020

2121
images_page = client.get('/images')

0 commit comments

Comments
 (0)