1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from __future__
import unicode_literals
21 from zipfile
import ZipFile
23 from flask
import session
24 from sqlalchemy
import cast
, Date
25 from werkzeug
.utils
import secure_filename
27 from indico
.web
.flask
.util
import send_file
28 from indico
.modules
.attachments
.forms
import MaterialsPackageForm
29 from indico
.modules
.attachments
.models
.attachments
import Attachment
, AttachmentFile
, AttachmentType
30 from indico
.modules
.attachments
.models
.folders
import AttachmentFolder
33 class MaterialsPackageMixin
:
36 form
= self
._prepare
_form
()
37 if form
.validate_on_submit():
38 return self
._generate
_zip
_file
(self
._filter
_attachments
(form
))
40 return self
.wp
.render_template('generate_package.html', self
._conf
, form
=form
)
42 def _prepare_form(self
):
43 form
= MaterialsPackageForm()
44 form
.sessions
.choices
= self
._load
_session
_data
()
45 form
.contributions
.choices
= self
._load
_contribution
_data
()
48 def _load_session_data(self
):
49 sessions
= self
._conf
.getSessionList()
50 return [(session
.getId(), session
.getTitle()) for session
in sessions
]
52 def _load_contribution_data(self
):
53 return [(contrib
.getId(), contrib
.getTitle()) for contrib
in self
._conf
.getContributionList()]
55 def _filter_attachments(self
, form
):
57 added_since
= form
.added_since
.data
58 attachments
.extend(self
._filter
_protected
(self
._filter
_top
_level
_attachments
(added_since
)))
59 if form
.sessions
.data
:
60 attachments
.extend(self
._filter
_protected
(self
._filter
_by
_sessions
(form
.sessions
.data
, added_since
)))
61 if form
.contributions
.data
:
62 attachments
.extend(self
._filter
_protected
(self
._filter
_by
_contributions
(form
.contributions
.data
, added_since
)))
65 def _filter_protected(self
, attachments
):
66 return [attachment
for attachment
in attachments
if attachment
.can_access(session
.user
)]
68 def _filter_top_level_attachments(self
, added_since
):
69 query
= self
._build
_base
_query
().filter(AttachmentFolder
.linked_object
== self
._conf
)
72 query
= self
._filter
_by
_date
(query
, added_since
)
76 def _build_base_query(self
):
77 return Attachment
.find(Attachment
.type == AttachmentType
.file, ~AttachmentFolder
.is_deleted
,
78 ~Attachment
.is_deleted
, AttachmentFolder
.event_id
== int(self
._conf
.getId()),
79 _join
=AttachmentFolder
)
81 def _filter_by_sessions(self
, session_ids
, added_since
):
82 query
= self
._build
_base
_query
().filter(AttachmentFolder
.session_id
.in_(session_ids
))
85 query
= self
._filter
_by
_date
(query
, added_since
)
89 def _filter_by_contributions(self
, contribution_ids
, added_since
):
90 query
= self
._build
_base
_query
().filter(AttachmentFolder
.contribution_id
.in_(contribution_ids
))
93 query
= self
._filter
_by
_date
(query
, added_since
)
97 def _filter_by_date(self
, query
, added_since
):
98 return query
.filter(cast(AttachmentFile
.created_dt
, Date
) >= added_since
)
100 def _generate_zip_file(self
, attachments
):
101 temp_file
= tempfile
.NamedTemporaryFile('w')
102 with
ZipFile(temp_file
.name
, 'w', allowZip64
=True) as zip_handler
:
103 for attachment
in attachments
:
104 if not attachment
.folder
.is_default
:
105 name
= os
.path
.join(os
.path
.join(secure_filename(attachment
.folder
.title
), attachment
.file.filename
))
107 name
= attachment
.file.filename
109 with attachment
.file.storage
.get_local_path(attachment
.file.storage_file_id
) as filepath
:
110 zip_handler
.write(filepath
, name
)
112 return send_file('attachments.zip', temp_file
.name
, 'application/zip', inline
=False)