-
Notifications
You must be signed in to change notification settings - Fork 2k
/
forms.py
271 lines (222 loc) · 9.32 KB
/
forms.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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
import os, logging
import ckan.authz as authz
from ckan.logic import NotAuthorized
from ckan.logic.schema import group_form_schema, default_package_schema
from ckan.lib import base
from ckan.lib.base import c, model, abort, request
from ckan.lib.base import redirect, _, config, h
from ckan.lib.navl.dictization_functions import DataError
from ckan.plugins import IGroupForm, IDatasetForm, IConfigurer, IRoutes
from ckan.plugins import implements, SingletonPlugin
from ckan.logic import check_access
from ckan.lib.navl.validators import (ignore_missing,
not_empty,
empty,
ignore,
keep_extras,
)
log = logging.getLogger(__name__)
class OrganizationForm(SingletonPlugin):
"""
This plugin implements an IGroupForm for form associated with a
organization group. ``IConfigurer`` is used to add the local template
path and the IGroupForm supplies the custom form.
"""
implements(IGroupForm, inherit=True)
implements(IConfigurer, inherit=True)
implements(IRoutes)
implements(IConfigurer)
def before_map(self, map):
controller = 'ckanext.organizations.controllers:OrganizationController'
map.connect('/organization/users/{id}', controller=controller, action='users')
map.connect('/organization/apply/{id}', controller=controller, action='apply')
map.connect('/organization/apply', controller=controller, action='apply')
map.connect('/organization/edit/{id}', controller='group', action='edit')
map.connect('/organization/new', controller='group', action='new')
map.connect('/organization/{id}', controller='group', action='read')
map.connect('/organization', controller='group', action='index')
map.redirect('/organizations', '/organization')
return map
def after_map(self, map):
return map
def update_config(self, config):
"""
This IConfigurer implementation causes CKAN to look in the
```templates``` directory when looking for the group_form()
"""
here = os.path.dirname(__file__)
rootdir = os.path.dirname(os.path.dirname(here))
template_dir = os.path.join(rootdir, 'ckanext',
'organizations', 'templates')
config['extra_template_paths'] = ','.join([template_dir,
config.get('extra_template_paths', '')])
# Override /group/* as the default groups urls
config['ckan.default.group_type'] = 'organization'
def new_template(self):
"""
Returns a string representing the location of the template to be
rendered for the new page
"""
return 'organization_new.html'
def index_template(self):
"""
Returns a string representing the location of the template to be
rendered for the index page
"""
return 'organization_index.html'
def read_template(self):
"""
Returns a string representing the location of the template to be
rendered for the read page
"""
return 'organization_read.html'
def history_template(self):
"""
Returns a string representing the location of the template to be
rendered for the read page
"""
return 'organization_history.html'
def group_form(self):
"""
Returns a string representing the location of the template to be
rendered. e.g. "forms/group_form.html".
"""
return 'organization_form.html'
def group_types(self):
"""
Returns an iterable of group type strings.
If a request involving a group of one of those types is made, then
this plugin instance will be delegated to.
There must only be one plugin registered to each group type. Any
attempts to register more than one plugin instance to a given group
type will raise an exception at startup.
"""
return ["organization"]
def is_fallback(self):
"""
Returns true iff this provides the fallback behaviour, when no other
plugin instance matches a group's type.
As this is not the fallback controller we should return False. If
we were wanting to act as the fallback, we'd return True
"""
return False
def form_to_db_schema(self):
"""
Returns the schema for mapping group data from a form to a format
suitable for the database.
"""
return group_form_schema()
def db_to_form_schema(self):
"""
Returns the schema for mapping group data from the database into a
format suitable for the form (optional)
"""
return group_form_schema()
def check_data_dict(self, data_dict):
"""
Check if the return data is correct.
raise a DataError if not.
"""
def setup_template_variables(self, context, data_dict):
"""
Add variables to c just prior to the template being rendered. We should
use the available groups for the current user, but should be optional
in case this is a top level group
"""
c.user_groups = c.userobj.get_groups('organization')
local_ctx = {'model': model, 'session': model.Session,
'user': c.user or c.author}
try:
check_access('group_create', local_ctx)
c.is_superuser_or_groupadmin = True
except NotAuthorized:
c.is_superuser_or_groupadmin = False
if 'group' in context:
group = context['group']
# Only show possible groups where the current user is a member
c.possible_parents = c.userobj.get_groups('organization', 'admin')
c.parent = None
grps = group.get_groups('organization')
if grps:
c.parent = grps[0]
c.users = group.members_of_type(model.User)
class OrganizationDatasetForm(SingletonPlugin):
implements(IDatasetForm, inherit=True)
def is_fallback(self):
return True
def package_types(self):
return ['dataset']
def new_template(self):
"""
Returns a string representing the location of the template to be
rendered for the new page
"""
return 'package/new.html'
def comments_template(self):
"""
Returns a string representing the location of the template to be
rendered for the comments page
"""
return 'package/comments.html'
def search_template(self):
"""
Returns a string representing the location of the template to be
rendered for the search page (if present)
"""
return 'package/search.html'
def read_template(self):
"""
Returns a string representing the location of the template to be
rendered for the read page
"""
return 'package/read.html'
def history_template(self):
"""
Returns a string representing the location of the template to be
rendered for the history page
"""
return 'package/history.html'
def package_form(self):
return 'organization_package_form.html'
def db_to_form_schema(self):
'''This is an interface to manipulate data from the database
into a format suitable for the form (optional)'''
#schema = default_package_schema()
#schema['groups']['capacity'] = [ ignore_missing, unicode ]
#return schema
def form_to_db_schema(self):
schema = default_package_schema()
schema['groups']['capacity'] = [ ignore_missing, unicode ]
return schema
def check_data_dict(self, data_dict, schema=None):
'''Check if the return data is correct, mostly for checking out
if spammers are submitting only part of the form'''
# Resources might not exist yet (eg. Add Dataset)
surplus_keys_schema = ['__extras', '__junk', 'state', 'groups',
'extras_validation', 'save', 'return_to',
'resources', 'type']
# if not schema:
# schema = self.form_to_db_schema()
# schema_keys = schema.keys()
# keys_in_schema = set(schema_keys) - set(surplus_keys_schema)
# missing_keys = keys_in_schema - set(data_dict.keys())
# if missing_keys:
# log.info('incorrect form fields posted, missing %s' % missing_keys)
# raise DataError(data_dict)
def setup_template_variables(self, context, data_dict):
from pylons import config
data_dict.update({'available_only':True})
c.groups_available = c.userobj and c.userobj.get_groups('organization') or []
c.licences = [('', '')] + base.model.Package.get_license_options()
c.is_sysadmin = authz.Authorizer().is_sysadmin(c.user)
## This is messy as auths take domain object not data_dict
context_pkg = context.get('package', None)
pkg = context_pkg or c.pkg
if pkg:
try:
if not context_pkg:
context['package'] = pkg
check_access('package_change_state', context)
c.auth_for_change_state = True
except NotAuthorized:
c.auth_for_change_state = False