-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathnotebook.py
207 lines (178 loc) · 7.6 KB
/
notebook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# -*- coding: utf-8 -*-
#
# This file is part of CERN Analysis Preservation Framework.
# Copyright (C) 2016 CERN.
#
# CERN Analysis Preservation Framework is free software; you can redistribute
# it and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# CERN Analysis Preservation Framework is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CERN Analysis Preservation Framework; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, CERN does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.
"""Serializer for deposit reviews."""
from __future__ import absolute_import, print_function
import requests
from flask import request
from flask_login import current_user
from invenio_deposit.api import index
from invenio_deposit.utils import mark_as_action
from cap.modules.deposit.errors import CERNBoxError
from cap.modules.deposit.permissions import UpdateDepositPermission
from cap.modules.deposit.utils import get_cernbox_creds, get_cern_common_name
class CERNBoxProvider(object):
"""Integration for CERNBox, upload files and share them."""
def init_cernbox_storage(self):
"""
Initialize CERNBox for use with SWAN.
- Create a folder named after the analysis ID in CERNBox.
- Share the folder with the analysis owner, give full permissions
- the CERN common_name is required
"""
username = get_cern_common_name(current_user)
if username:
depid = self['_deposit']['id']
# 1. create cernbox folder
response = self._create_folder(depid)
if not response.ok:
raise CERNBoxError('Could not create CERNBox folder.')
# 2. share with current user
response = self._share_folder(depid, 0, username, 'admin')
if not response.ok:
raise CERNBoxError(f'Could not share with user {username}.')
# 3. save to deposit and update
access = {'read': [], 'update': [], 'admin': []}
self['_notebook'] = {
'files': [],
'access': {
'users': access,
'groups': access
}
}
@index
@mark_as_action
def cernboxupload(self, pid=None):
"""Upload an existing file, to the associated CERNBox folder."""
with UpdateDepositPermission(self).require(403):
if request:
data = request.get_json()
filename = data.get('filename')
filepath = data.get('filepath')
# retrieve file contents
try:
file_obj = self.files[filename].obj
file_content = open(file_obj.file.uri).read()
except KeyError:
raise CERNBoxError(
f'File {filename} could not be found in the analysis.')
# apply new path (optional)
new_file = f'{filepath}/{filename}' if filepath else filename
depid = self['_deposit']['id']
response = self._upload_to_folder(
depid, new_file, file_content)
if not response.ok:
raise CERNBoxError(f'Upload of {filename} failed.')
self['_notebook']['files'].append(new_file)
return self
@index
@mark_as_action
def cernboxshare(self, pid=None):
"""Share your analysis folder, with groups/users."""
with UpdateDepositPermission(self).require(403):
if request:
data = request.get_json()
groups = data.get('groups', [])
users = data.get('users', [])
perm = data.get('permission')
depid = self['_deposit']['id']
for group in groups:
response = self._share_folder(depid, 1, group, perm)
if not response.ok:
raise CERNBoxError(
f'Could not provide {perm} permission to {group}.')
self['_notebooks']['access']['groups'][perm].append(group)
for user in users:
response = self._share_folder(depid, 0, user, perm)
if not response.ok:
raise CERNBoxError(
f'Could not provide {perm} permission to {user}.')
self['_notebooks']['access']['users'][perm].append(user)
return self
@index
@mark_as_action
def cernboxdelete(self, pid=None):
"""Share your analysis folder, with groups/users."""
with UpdateDepositPermission(self).require(403):
if request:
data = request.get_json()
path = data.get('permission')
depid = self['_deposit']['id']
path = f'{depid}/{path}'
response = self._delete_folder(path)
if not response.ok:
raise CERNBoxError(f'Could not delete {path}.')
# need to delete files as well, need to think about that
# files - folders, how to handle?
# maybe save them differently? tree structure?
return self
def _create_folder(self, depid):
"""Create a folder in CERNBox, named after the current analysis."""
host, user, password, auth = get_cernbox_creds()
response = requests.request(
'MKCOL',
url=f'{host}/remote.php/dav/files/{user}/{depid}',
auth=auth
)
return response
def _upload_to_folder(self, depid, new_file, file_content):
"""Upload a file to CERNBox."""
host, user, password, auth = get_cernbox_creds()
response = requests.put(
url=f'{host}/remote.php/dav/files/{user}/{depid}/{new_file}',
data=file_content,
auth=auth,
headers={'Content-Type': 'application/octet-stream'}
)
return response
def _share_folder(self, depid, _type, _with, perm):
"""
Share request for users/groups, providing specific permissions.
more info: https://doc.owncloud.org/server/9.0/developer_manual/core/ocs-share-api.html # noqa
Important: shareType: 0 for users, 1 for groups
permissions: 1-read, 2-update, 31-admin
"""
host, _, _, auth = get_cernbox_creds()
permissions = {
'read': 1,
'update': 2,
'admin': 31
}
response = requests.post(
url=f'{host}/ocs/v2.php/apps/files_sharing/api/v1/shares?format=json', # noqa
data={
"shareType": _type,
"shareWith": _with,
"permissions": permissions[perm],
"path": f'/{depid}'
},
auth=auth
)
return response
def _delete_folder(self, path):
host, user, password, auth = get_cernbox_creds()
response = requests.delete(
url=f'{host}/remote.php/dav/files/{user}/{path}',
auth=auth
)
return response