1
|
|
|
################################################################# |
2
|
|
|
# MET v2 Metadate Explorer Tool |
3
|
|
|
# |
4
|
|
|
# This Software is Open Source. See License: https://github.com/TERENA/met/blob/master/LICENSE.md |
5
|
|
|
# Copyright (c) 2012, TERENA All rights reserved. |
6
|
|
|
# |
7
|
|
|
# This Software is based on MET v1 developed for TERENA by Yaco Sistemas, http://www.yaco.es/ |
8
|
|
|
# MET v2 was developed for TERENA by Tamim Ziai, DAASI International GmbH, http://www.daasi.de |
9
|
|
|
# Current version of MET has been revised for performance improvements by Andrea Biancini, |
10
|
|
|
# Consortium GARR, http://www.garr.it |
11
|
|
|
######################################################################################### |
12
|
|
|
|
13
|
|
|
import re, time |
14
|
|
|
import pytz |
15
|
|
|
import operator |
16
|
|
|
import simplejson as json |
17
|
|
|
from urllib import unquote |
18
|
|
|
from datetime import datetime |
19
|
|
|
from dateutil import tz |
20
|
|
|
|
21
|
|
|
from django.conf import settings |
22
|
|
|
from django.db.models import Count, Q |
23
|
|
|
from django.contrib import messages |
24
|
|
|
from django.contrib.auth import logout |
25
|
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
26
|
|
|
from django.core.urlresolvers import reverse |
27
|
|
|
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest |
28
|
|
|
from django.shortcuts import render_to_response, get_object_or_404 |
29
|
|
|
from django.template import RequestContext |
30
|
|
|
from django.utils.translation import ugettext_lazy as _ |
31
|
|
|
from django.utils import timezone |
32
|
|
|
|
33
|
|
|
from chartit import DataPool, Chart |
34
|
|
|
|
35
|
|
|
from met.metadataparser.decorators import user_can_edit |
36
|
|
|
from met.metadataparser.models import Federation, Entity, EntityStat, EntityCategory, TOP_LENGTH, FEDERATION_TYPES |
37
|
|
|
from met.metadataparser.forms import (FederationForm, EntityForm, EntityCommentForm, |
38
|
|
|
EntityProposalForm, ServiceSearchForm, ChartForm, SearchEntitiesForm) |
39
|
|
|
|
40
|
|
|
from met.metadataparser.summary_export import export_summary |
41
|
|
|
from met.metadataparser.query_export import export_query_set |
42
|
|
|
from met.metadataparser.entity_export import export_entity |
43
|
|
|
from met.metadataparser.xmlparser import DESCRIPTOR_TYPES |
44
|
|
|
from met.metadataparser.utils import send_mail |
45
|
|
|
|
46
|
|
|
if settings.PROFILE: |
47
|
|
|
from silk.profiling.profiler import silk_profile as profile |
48
|
|
|
else: |
49
|
|
|
from met.metadataparser.templatetags.decorators import noop_decorator as profile |
50
|
|
|
|
51
|
|
|
RESCUE_SLASH = re.compile(r"^(http(?:|s):/)([^/])") |
52
|
|
|
|
53
|
|
|
def increment_current_toplength(request): |
54
|
|
|
current_top_length = request.session.get('currentTopLength', TOP_LENGTH) |
55
|
|
|
current_top_length += TOP_LENGTH |
56
|
|
|
|
57
|
|
|
if current_top_length > Entity.objects.all().count(): |
58
|
|
|
current_top_length -= TOP_LENGTH |
59
|
|
|
|
60
|
|
|
request.session['currentTopLength'] = current_top_length |
61
|
|
|
return HttpResponseRedirect(reverse('index')) |
62
|
|
|
|
63
|
|
|
def decrement_current_toplength(request): |
64
|
|
|
current_top_length = request.session.get('currentTopLength', TOP_LENGTH) |
65
|
|
|
current_top_length -= TOP_LENGTH |
66
|
|
|
|
67
|
|
|
if current_top_length <= 0: |
68
|
|
|
current_top_length = TOP_LENGTH |
69
|
|
|
|
70
|
|
|
request.session['currentTopLength'] = current_top_length |
71
|
|
|
return HttpResponseRedirect(reverse('index')) |
72
|
|
|
|
73
|
|
|
def _index_export(export, export_format, objects): |
74
|
|
|
counters = ( |
75
|
|
|
('all', {}), |
76
|
|
|
('IDPSSO', {'types__xmlname': 'IDPSSODescriptor'}), |
77
|
|
|
('SPSSO', {'types__xmlname': 'SPSSODescriptor'}), |
78
|
|
|
) |
79
|
|
|
|
80
|
|
|
if not export in ['interfederations', 'federations', 'most_federated_entities']: |
81
|
|
|
return HttpResponseBadRequest('Not valid export query') |
82
|
|
|
|
83
|
|
|
if export == 'most_federated_entities': |
84
|
|
|
return export_query_set(export_format, objects['most_federated_entities'], |
85
|
|
|
'most_federated_entities', ('entityid', 'types', 'name', 'federations')) |
86
|
|
|
else: |
87
|
|
|
return export_summary(export_format, objects[export], |
88
|
|
|
'entity_set', '%s_summary' % export, |
89
|
|
|
counters) |
90
|
|
|
|
91
|
|
|
@profile(name='Index page') |
92
|
|
|
def index(request): |
93
|
|
|
ff = Federation.objects.all().order_by('name') |
94
|
|
|
federations = [] |
95
|
|
|
interfederations = [] |
96
|
|
|
for f in ff: |
97
|
|
|
if f.is_interfederation: |
98
|
|
|
interfederations.append(f) |
99
|
|
|
else: |
100
|
|
|
federations.append(f) |
101
|
|
|
|
102
|
|
|
cc = Entity.objects.values('federations__id', 'types__xmlname').annotate(Count('federations__id'), Count('types__xmlname')) |
103
|
|
|
counts = {} |
104
|
|
|
for curtype in DESCRIPTOR_TYPES: |
105
|
|
|
counts[curtype] = [] |
106
|
|
|
for c in cc: |
107
|
|
|
if c['types__xmlname'] == curtype: |
108
|
|
|
counts[curtype].append(c) |
109
|
|
|
counts['All'] = Entity.objects.values('federations__id').annotate(Count('federations__id')) |
110
|
|
|
|
111
|
|
|
totals = Entity.objects.values('types__xmlname').annotate(Count('types__xmlname')) |
112
|
|
|
|
113
|
|
|
# Entities with count how many federations belongs to, and sorted by most first |
114
|
|
|
current_top_length = request.session.get('currentTopLength', TOP_LENGTH) |
115
|
|
|
most_federated_entities = Entity.get_most_federated_entities(maxlength=current_top_length, cache_expire=24*60*60) |
116
|
|
|
|
117
|
|
|
params = { |
118
|
|
|
'settings': settings, |
119
|
|
|
'interfederations': interfederations, |
120
|
|
|
'federations': federations, |
121
|
|
|
'entity_types': DESCRIPTOR_TYPES, |
122
|
|
|
'federation_path': request.path, |
123
|
|
|
'counts': counts, |
124
|
|
|
'totals': totals, |
125
|
|
|
'most_federated_entities': most_federated_entities, |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
export = request.GET.get('export', None) |
129
|
|
|
export_format = request.GET.get('format', None) |
130
|
|
|
if export and export_format: |
131
|
|
|
return _index_export(export, export_format, params) |
132
|
|
|
|
133
|
|
|
return render_to_response('metadataparser/index.html', params, context_instance=RequestContext(request)) |
134
|
|
|
|
135
|
|
|
def _paginate_fed(ob_entities, page): |
136
|
|
|
paginator = Paginator(ob_entities, 20) |
137
|
|
|
|
138
|
|
|
try: |
139
|
|
|
ob_entities = paginator.page(page) |
140
|
|
|
except PageNotAnInteger: |
141
|
|
|
ob_entities = paginator.page(1) |
142
|
|
|
except EmptyPage: |
143
|
|
|
ob_entities = paginator.page(paginator.num_pages) |
144
|
|
|
|
145
|
|
|
adjacent_pages = 5 |
146
|
|
|
page_range = [n for n in \ |
147
|
|
|
range(ob_entities.number - adjacent_pages, ob_entities.number + adjacent_pages + 1) \ |
148
|
|
|
if n > 0 and n <= ob_entities.paginator.num_pages] |
149
|
|
|
|
150
|
|
|
return { |
151
|
|
|
'page_range': page_range, |
152
|
|
|
'cur_page_number': ob_entities.number, |
153
|
|
|
'num_pages': ob_entities.paginator.num_pages, |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
@profile(name='Federation view') |
157
|
|
|
def federation_view(request, federation_slug=None): |
158
|
|
|
if federation_slug: |
159
|
|
|
request.session['%s_process_done' % federation_slug] = False |
160
|
|
|
request.session['%s_num_entities' % federation_slug] = 0 |
161
|
|
|
request.session['%s_cur_entities' % federation_slug] = 0 |
162
|
|
|
request.session.save() |
163
|
|
|
|
164
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
165
|
|
|
categories = EntityCategory.objects.all().filter( |
166
|
|
|
Q(category_id__icontains=federation.registration_authority) | |
167
|
|
|
Q(category_id__icontains='http://refeds.org') | |
168
|
|
|
Q(category_id__icontains='http://www.geant.net')) |
169
|
|
|
|
170
|
|
|
ob_entities = Entity.objects.filter(federations__id=federation.id) |
171
|
|
|
entity_type = None |
172
|
|
|
if request.GET and 'entity_type' in request.GET: |
173
|
|
|
entity_type = request.GET['entity_type'] |
174
|
|
|
ob_entities = ob_entities.filter(types__xmlname=entity_type) |
175
|
|
|
|
176
|
|
|
entity_category = None |
177
|
|
|
if request.GET and 'entity_category' in request.GET: |
178
|
|
|
entity_category = request.GET['entity_category'] |
179
|
|
|
ob_entities = ob_entities.filter(entity_categories__category_id=entity_category) |
180
|
|
|
|
181
|
|
|
ob_entities = ob_entities.prefetch_related('types', 'federations') |
182
|
|
|
pagination = _paginate_fed(ob_entities, request.GET.get('page')) |
183
|
|
|
|
184
|
|
|
entities = [] |
185
|
|
|
for entity in ob_entities: |
186
|
|
|
entities.append({ |
187
|
|
|
'entityid': entity.entityid, |
188
|
|
|
'name': entity.name, |
189
|
|
|
'absolute_url': entity.get_absolute_url(), |
190
|
|
|
'types': [unicode(item) for item in entity.types.all()], |
191
|
|
|
'federations': [(unicode(item.name), item.get_absolute_url()) for item in entity.federations.all()], |
192
|
|
|
}) |
193
|
|
|
|
194
|
|
|
if 'format' in request.GET: |
195
|
|
|
return export_query_set(request.GET.get('format'), entities, |
196
|
|
|
'entities_search_result', ('entityid', 'types', 'federations')) |
197
|
|
|
|
198
|
|
|
context = RequestContext(request) |
199
|
|
|
user = context.get('user', None) |
200
|
|
|
add_entity = user and user.has_perm('metadataparser.add_federation') |
201
|
|
|
pie_chart = fed_pie_chart(request, federation.id) |
202
|
|
|
|
203
|
|
|
return render_to_response('metadataparser/federation_view.html', |
204
|
|
|
{'settings': settings, |
205
|
|
|
'federation': federation, |
206
|
|
|
'entity_types': DESCRIPTOR_TYPES, |
207
|
|
|
'entity_type': entity_type or 'All', |
208
|
|
|
'fed_types': dict(FEDERATION_TYPES), |
209
|
|
|
'entities': entities, |
210
|
|
|
'categories': categories, |
211
|
|
|
'show_filters': True, |
212
|
|
|
'add_entity': add_entity, |
213
|
|
|
'lang': request.GET.get('lang', 'en'), |
214
|
|
|
'update_entities': request.GET.get('update', 'false'), |
215
|
|
|
'statcharts': [pie_chart], |
216
|
|
|
'pagination': pagination, |
217
|
|
|
}, context_instance=context) |
218
|
|
|
|
219
|
|
|
|
220
|
|
|
@user_can_edit(Federation) |
221
|
|
|
def federation_edit_post(request, federation, form): |
222
|
|
|
modify = True if federation else False |
223
|
|
|
form.save() |
224
|
|
|
|
225
|
|
|
if not modify: |
226
|
|
|
form.instance.editor_users.add(request.user) |
227
|
|
|
if 'file' in form.changed_data or 'file_url' in form.changed_data: |
228
|
|
|
form.instance.process_metadata() |
229
|
|
|
|
230
|
|
|
messages.success(request, _('Federation %s successfully' % 'modified' if modify else 'created')) |
231
|
|
|
return HttpResponseRedirect(form.instance.get_absolute_url() + '?update=true') |
232
|
|
|
|
233
|
|
|
|
234
|
|
|
@user_can_edit(Federation) |
235
|
|
|
def federation_edit(request, federation_slug=None): |
236
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) if federation_slug else None |
237
|
|
|
|
238
|
|
|
if request.method == 'POST': |
239
|
|
|
form = FederationForm(request.POST, request.FILES, instance=federation) |
240
|
|
|
if not form.is_valid(): |
241
|
|
|
messages.error(request, _('Please correct the errors indicated below')) |
242
|
|
|
else: |
243
|
|
|
return federation_edit_post(request, federation, form) |
244
|
|
|
else: |
245
|
|
|
form = FederationForm(instance=federation) |
246
|
|
|
|
247
|
|
|
context = RequestContext(request) |
248
|
|
|
user = context.get('user', None) |
249
|
|
|
delete_federation = user and user.has_perm('metadataparser.delete_federation') |
250
|
|
|
return render_to_response('metadataparser/federation_edit.html', |
251
|
|
|
{'settings': settings, 'form': form, 'delete_federation': delete_federation}, |
252
|
|
|
context_instance=RequestContext(request)) |
253
|
|
|
|
254
|
|
|
|
255
|
|
|
@user_can_edit(Federation) |
256
|
|
|
def federation_update_entities(request, federation_slug=None): |
257
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
258
|
|
|
federation.process_metadata_entities(request=request, federation_slug=federation_slug) |
259
|
|
|
|
260
|
|
|
messages.success(request, _('Federation entities updated succesfully')) |
261
|
|
|
return HttpResponse("Done. All entities updated.", content_type='text/plain') |
262
|
|
|
|
263
|
|
|
|
264
|
|
|
def entityupdate_progress(request, federation_slug=None): |
265
|
|
|
data = { 'done': False } |
266
|
|
|
if federation_slug: |
267
|
|
|
data = { 'done': request.session.get('%s_process_done' % federation_slug, False), |
268
|
|
|
'tot': request.session.get('%s_num_entities' % federation_slug, 0), |
269
|
|
|
'num': request.session.get('%s_cur_entities' % federation_slug, 0) } |
270
|
|
|
|
271
|
|
|
return HttpResponse(json.dumps(data), content_type='application/javascript') |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
@user_can_edit(Federation, True) |
275
|
|
|
def federation_delete(request, federation_slug): |
276
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
277
|
|
|
|
278
|
|
|
for entity in federation.entity_set.all(): |
279
|
|
|
if len(entity.federations.all()) == 1: |
280
|
|
|
entity.delete() |
281
|
|
|
|
282
|
|
|
messages.success(request, |
283
|
|
|
_(u"%(federation)s federation was deleted successfully" |
284
|
|
|
% {'federation': unicode(federation)})) |
285
|
|
|
federation.delete() |
286
|
|
|
return HttpResponseRedirect(reverse('index')) |
287
|
|
|
|
288
|
|
|
|
289
|
|
|
@profile(name='Index charts') |
290
|
|
|
def federation_charts(request, federation_slug=None): |
291
|
|
|
if federation_slug is None: |
292
|
|
|
federation = None |
293
|
|
|
else: |
294
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
295
|
|
|
|
296
|
|
|
if request.method == 'POST': |
297
|
|
|
form = ChartForm(request.POST, request.FILES, instance=federation) |
298
|
|
|
|
299
|
|
|
if form.is_valid(): |
300
|
|
|
stats_config_dict = getattr(settings, "STATS") |
301
|
|
|
service_terms = stats_config_dict['statistics']['entity_by_type']['terms'] |
302
|
|
|
protocol_terms = stats_config_dict['statistics']['entity_by_protocol']['terms'] |
303
|
|
|
|
304
|
|
|
protocols = stats_config_dict['protocols'] |
305
|
|
|
|
306
|
|
|
from_time = datetime.fromordinal(form.cleaned_data['fromDate'].toordinal()) |
307
|
|
|
if timezone.is_naive(from_time): |
308
|
|
|
from_time = pytz.utc.localize(from_time) |
309
|
|
|
to_time = datetime.fromordinal(form.cleaned_data['toDate'].toordinal() + 1) |
310
|
|
|
if timezone.is_naive(to_time): |
311
|
|
|
to_time = pytz.utc.localize(to_time) |
312
|
|
|
|
313
|
|
|
service_stats = EntityStat.objects.filter( federation=federation \ |
314
|
|
|
, feature__in = service_terms \ |
315
|
|
|
, time__gte = from_time \ |
316
|
|
|
, time__lte = to_time).order_by("time") |
317
|
|
|
|
318
|
|
|
protocol_stats = EntityStat.objects.filter( federation=federation \ |
319
|
|
|
, feature__in = protocol_terms \ |
320
|
|
|
, time__gte = from_time \ |
321
|
|
|
, time__lte = to_time).order_by("time") |
322
|
|
|
|
323
|
|
|
s_chart = stats_chart(stats_config_dict, request, service_stats, 'entity_by_type') |
324
|
|
|
|
325
|
|
|
p_chart = stats_chart(stats_config_dict, request, protocol_stats, 'entity_by_protocol', protocols) |
326
|
|
|
|
327
|
|
|
return render_to_response('metadataparser/federation_chart.html', |
328
|
|
|
{'form': form, |
329
|
|
|
'statcharts': [s_chart, p_chart], |
330
|
|
|
}, |
331
|
|
|
context_instance=RequestContext(request)) |
332
|
|
|
|
333
|
|
|
else: |
334
|
|
|
messages.error(request, _('Please correct the errors indicated' |
335
|
|
|
' below')) |
336
|
|
|
else: |
337
|
|
|
form = ChartForm(instance=federation) |
338
|
|
|
|
339
|
|
|
return render_to_response('metadataparser/federation_chart.html', |
340
|
|
|
{'settings': settings, 'form': form}, |
341
|
|
|
context_instance=RequestContext(request)) |
342
|
|
|
|
343
|
|
|
|
344
|
|
|
def stats_chart(stats_config_dict, request, stats, entity, protocols=None): |
345
|
|
|
terms = stats_config_dict['statistics'][entity]['terms'] |
346
|
|
|
title = stats_config_dict['statistics'][entity]['title'] |
347
|
|
|
x_title = stats_config_dict['statistics'][entity]['x_title'] |
348
|
|
|
y_title = stats_config_dict['statistics'][entity]['y_title'] |
349
|
|
|
chart_type = 'column' |
350
|
|
|
stacking = True |
351
|
|
|
term_names = stats_config_dict['feature_names'] |
352
|
|
|
time_format = stats_config_dict['time_format'] |
353
|
|
|
statdata = _create_statdata('bar', stats, terms, term_names) |
354
|
|
|
|
355
|
|
|
series_options = [] |
356
|
|
|
for stack in range(len(protocols) if protocols else 1): |
357
|
|
|
for term in terms: |
358
|
|
|
if not protocols or term.endswith(protocols[stack]): |
359
|
|
|
series_options += \ |
360
|
|
|
[{'options':{ |
361
|
|
|
'type': chart_type, |
362
|
|
|
'stacking': stacking, |
363
|
|
|
'stack': stack, |
364
|
|
|
}, |
365
|
|
|
'terms':{ |
366
|
|
|
'time_%s' %term: [{term_names[term]: {'stack': stack, }}], |
367
|
|
|
}}] |
368
|
|
|
|
369
|
|
|
chart_options = _get_chart_options('bar', title, x_title, y_title) |
370
|
|
|
|
371
|
|
|
return Chart( |
372
|
|
|
datasource = statdata, |
373
|
|
|
series_options = series_options, |
374
|
|
|
chart_options = chart_options, |
375
|
|
|
x_sortf_mapf_mts=(None, lambda i: datetime.fromtimestamp(time.mktime(i.replace(tzinfo=tz.gettz('UTC')).astimezone(tz.tzlocal()).timetuple())).strftime(time_format), False) |
376
|
|
|
) |
377
|
|
|
|
378
|
|
|
|
379
|
|
|
|
380
|
|
|
def _create_statdata(chart_type, stats, terms=None, term_names=None): |
381
|
|
|
if chart_type == 'bar': |
382
|
|
|
statdata = DataPool( |
383
|
|
|
series=[{'options': { |
384
|
|
|
'source': stats.filter(feature=term)}, |
385
|
|
|
'legend_by': 'feature', |
386
|
|
|
'terms': [{'time_%s' %term :'time'}, |
387
|
|
|
{term_names[term] : 'value', 'name': 'feature'}] |
388
|
|
|
} for term in terms] |
389
|
|
|
) |
390
|
|
|
elif chart_type == 'pie': |
391
|
|
|
statdata = DataPool( |
392
|
|
|
series=[{'options': { 'source': stats }, |
393
|
|
|
'legend_by': 'feature', |
394
|
|
|
'terms': ['feature', 'value'], |
395
|
|
|
}] |
396
|
|
|
) |
397
|
|
|
else: |
398
|
|
|
statdata = None |
399
|
|
|
|
400
|
|
|
return statdata |
401
|
|
|
|
402
|
|
|
def _get_chart_options(chart_type, title=None, x_title=None, y_title=None): |
403
|
|
|
if chart_type == 'bar': |
404
|
|
|
chart_options = {'title': { 'text': title }, |
405
|
|
|
'xAxis': { |
406
|
|
|
'title': { 'text': x_title }, |
407
|
|
|
'labels': { |
408
|
|
|
'rotation': -45, |
409
|
|
|
'align': 'right' |
410
|
|
|
}, |
411
|
|
|
'max': 10, |
412
|
|
|
}, |
413
|
|
|
'yAxis': { |
414
|
|
|
'title': { 'text': y_title }, |
415
|
|
|
'minorTickInterval': 'auto' |
416
|
|
|
}, |
417
|
|
|
'credits': { 'enabled': False }, |
418
|
|
|
'scrollbar': { 'enabled': True }, |
419
|
|
|
'zoomType': 'xy', |
420
|
|
|
} |
421
|
|
|
elif chart_type == 'pie': |
422
|
|
|
chart_options = { |
423
|
|
|
'title': { 'text': ' ' }, |
424
|
|
|
'credits': { 'enabled': False } |
425
|
|
|
} |
426
|
|
|
else: |
427
|
|
|
chart_options = None |
428
|
|
|
|
429
|
|
|
return chart_options |
430
|
|
|
|
431
|
|
|
def fed_pie_chart(request, federation_id): |
432
|
|
|
stats_config_dict = getattr(settings, "STATS") |
433
|
|
|
terms = stats_config_dict['statistics']['entity_by_type']['terms'] |
434
|
|
|
stats = EntityStat.objects.filter(federation=federation_id, \ |
435
|
|
|
feature__in=terms).order_by('-time')[0:len(terms)] |
436
|
|
|
statdata = _create_statdata('pie', stats) |
437
|
|
|
series_options = \ |
438
|
|
|
[{'options': { 'type': 'pie', 'stacking': False, 'size': '70%' }, |
439
|
|
|
'terms':{ 'feature': [ 'value' ] }}] |
440
|
|
|
chart_options = _get_chart_options('pie') |
441
|
|
|
|
442
|
|
|
return Chart( |
443
|
|
|
datasource = statdata, |
444
|
|
|
series_options = series_options, |
445
|
|
|
chart_options = chart_options, |
446
|
|
|
) |
447
|
|
|
|
448
|
|
|
|
449
|
|
|
|
450
|
|
|
@profile(name='Entity view') |
451
|
|
|
def entity_view(request, entityid): |
452
|
|
|
entityid = unquote(entityid) |
453
|
|
|
entityid = RESCUE_SLASH.sub("\\1/\\2", entityid) |
454
|
|
|
|
455
|
|
|
entity = get_object_or_404(Entity, entityid=entityid) |
456
|
|
|
|
457
|
|
|
if 'federation' in request.GET: |
458
|
|
|
federation = get_object_or_404(Federation, slug=request.GET.get('federation')) |
459
|
|
|
entity.curfed = federation |
460
|
|
|
|
461
|
|
|
if 'format' in request.GET: |
462
|
|
|
return export_entity(request.GET.get('format'), entity) |
463
|
|
|
|
464
|
|
|
if 'viewxml' in request.GET: |
465
|
|
|
serialized = entity.xml |
466
|
|
|
response = HttpResponse(serialized, content_type='application/xml') |
467
|
|
|
return response |
468
|
|
|
|
469
|
|
|
return render_to_response('metadataparser/entity_view.html', |
470
|
|
|
{'settings': settings, |
471
|
|
|
'entity': entity, |
472
|
|
|
'lang': request.GET.get('lang', 'en') |
473
|
|
|
}, context_instance=RequestContext(request)) |
474
|
|
|
|
475
|
|
|
|
476
|
|
|
@user_can_edit(Entity) |
477
|
|
|
def entity_edit_post(request, form, federation, entity): |
478
|
|
|
form.save() |
479
|
|
|
if federation and not federation in form.instance.federations.all(): |
480
|
|
|
form.instance.federations.add(federation) |
481
|
|
|
form.instance.save() |
482
|
|
|
|
483
|
|
|
if entity: |
484
|
|
|
messages.success(request, _('Entity modified successfully')) |
485
|
|
|
else: |
486
|
|
|
messages.success(request, _('Entity created successfully')) |
487
|
|
|
|
488
|
|
|
return HttpResponseRedirect(form.instance.get_absolute_url()) |
489
|
|
|
|
490
|
|
|
|
491
|
|
|
|
492
|
|
|
@user_can_edit(Entity) |
493
|
|
|
def entity_edit(request, federation_slug=None, entity_id=None): |
494
|
|
|
entity = None |
495
|
|
|
federation = None |
496
|
|
|
if federation_slug: |
497
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
498
|
|
|
if entity_id: |
499
|
|
|
entity = get_object_or_404(Entity, id=entity_id, |
500
|
|
|
federations__id=federation.id) |
501
|
|
|
if entity_id and not federation_slug: |
502
|
|
|
entity = get_object_or_404(Entity, id=entity_id) |
503
|
|
|
|
504
|
|
|
if request.method == 'POST': |
505
|
|
|
form = EntityForm(request.POST, request.FILES, instance=entity) |
506
|
|
|
if form.is_valid(): |
507
|
|
|
return entity_edit_post(request, form, federation, entity) |
508
|
|
|
else: |
509
|
|
|
messages.error(request, _('Please correct the errors indicated below')) |
510
|
|
|
else: |
511
|
|
|
form = EntityForm(instance=entity) |
512
|
|
|
|
513
|
|
|
return render_to_response('metadataparser/entity_edit.html', |
514
|
|
|
{'settings': settings, |
515
|
|
|
'form': form, |
516
|
|
|
'federation': federation}, |
517
|
|
|
context_instance=RequestContext(request)) |
518
|
|
|
|
519
|
|
|
|
520
|
|
|
@user_can_edit(Entity, True) |
521
|
|
|
def entity_delete(request, entity_id): |
522
|
|
|
entity = get_object_or_404(Entity, id=entity_id) |
523
|
|
|
messages.success(request, |
524
|
|
|
_(u"%(entity)s entity was deleted successfully" |
525
|
|
|
% {'entity': unicode(entity)})) |
526
|
|
|
entity.delete() |
527
|
|
|
return HttpResponseRedirect(reverse('index')) |
528
|
|
|
|
529
|
|
|
|
530
|
|
|
def entity_comment(request, federation_slug=None, entity_id=None): |
531
|
|
|
entity = None |
532
|
|
|
federation = None |
533
|
|
|
if federation_slug: |
534
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
535
|
|
|
if entity_id: |
536
|
|
|
entity = get_object_or_404(Entity, id=entity_id, |
537
|
|
|
federations__id=federation.id) |
538
|
|
|
if entity_id and not federation_slug: |
539
|
|
|
entity = get_object_or_404(Entity, id=entity_id) |
540
|
|
|
|
541
|
|
|
if request.method == 'POST': |
542
|
|
|
form = EntityCommentForm(request.POST, request.FILES, instance=entity) |
543
|
|
|
if form.is_valid(): |
544
|
|
|
mail_config = getattr(settings, "MAIL_CONFIG") |
545
|
|
|
try: |
546
|
|
|
subject = mail_config['comment_subject'] %entity |
547
|
|
|
send_mail(form.data['email'], subject, form.data['comment']) |
548
|
|
|
messages.success(request, _('Comment posted successfully')) |
549
|
|
|
except Exception, errorMessage: |
550
|
|
|
messages.error(request, _('Comment could not be posted successfully: %s' %errorMessage)) |
551
|
|
|
|
552
|
|
|
return HttpResponseRedirect(form.instance.get_absolute_url()) |
553
|
|
|
|
554
|
|
|
else: |
555
|
|
|
messages.error(request, _('Please correct the errors indicated' |
556
|
|
|
' below')) |
557
|
|
|
else: |
558
|
|
|
form = EntityCommentForm(instance=entity) |
559
|
|
|
|
560
|
|
|
return render_to_response('metadataparser/entity_comment.html', |
561
|
|
|
{'settings': settings, |
562
|
|
|
'form': form, |
563
|
|
|
}, |
564
|
|
|
context_instance=RequestContext(request)) |
565
|
|
|
|
566
|
|
|
|
567
|
|
|
def entity_proposal(request, federation_slug=None, entity_id=None): |
568
|
|
|
entity = None |
569
|
|
|
federation = None |
570
|
|
|
if federation_slug: |
571
|
|
|
federation = get_object_or_404(Federation, slug=federation_slug) |
572
|
|
|
if entity_id: |
573
|
|
|
entity = get_object_or_404(Entity, id=entity_id, |
574
|
|
|
federations__id=federation.id) |
575
|
|
|
if entity_id and not federation_slug: |
576
|
|
|
entity = get_object_or_404(Entity, id=entity_id) |
577
|
|
|
|
578
|
|
|
if request.method == 'POST': |
579
|
|
|
form = EntityProposalForm(request.POST, request.FILES, instance=entity) |
580
|
|
|
|
581
|
|
|
if form.is_valid(): |
582
|
|
|
mail_config = getattr(settings, "MAIL_CONFIG") |
583
|
|
|
try: |
584
|
|
|
subject = mail_config['proposal_subject'] %entity |
585
|
|
|
my_dict = dict(form.data.iterlists()) |
586
|
|
|
body = mail_config['proposal_body'] % (entity, ', '.join(my_dict['federations']), form.data['comment']) |
587
|
|
|
send_mail(form.data['email'], subject, body) |
588
|
|
|
messages.success(request, _('Proposal posted successfully')) |
589
|
|
|
except Exception, errorMessage: |
590
|
|
|
messages.error(request, _('Proposal could not be posted successfully: %s' %errorMessage)) |
591
|
|
|
|
592
|
|
|
return HttpResponseRedirect(form.instance.get_absolute_url()) |
593
|
|
|
|
594
|
|
|
else: |
595
|
|
|
messages.error(request, _('Please correct the errors indicated' |
596
|
|
|
' below')) |
597
|
|
|
else: |
598
|
|
|
form = EntityProposalForm(instance=entity) |
599
|
|
|
|
600
|
|
|
return render_to_response('metadataparser/entity_proposal.html', |
601
|
|
|
{'settings': settings, |
602
|
|
|
'form': form, |
603
|
|
|
}, |
604
|
|
|
context_instance=RequestContext(request)) |
605
|
|
|
|
606
|
|
|
def search_service(request): |
607
|
|
|
filters = {} |
608
|
|
|
objects = [] |
609
|
|
|
|
610
|
|
|
if 'entityid' in request.GET: |
611
|
|
|
form = ServiceSearchForm(request.GET) |
612
|
|
|
if form.is_valid(): |
613
|
|
|
entityid = form.cleaned_data['entityid'] |
614
|
|
|
entityid = entityid.strip() |
615
|
|
|
filters['entityid__icontains'] = entityid |
616
|
|
|
else: |
617
|
|
|
form = ServiceSearchForm() |
618
|
|
|
entity_type = request.GET.get('entity_type', None) |
619
|
|
|
|
620
|
|
|
if entity_type: |
621
|
|
|
filters['entity_type'] = entity_type |
622
|
|
|
|
623
|
|
|
if filters: |
624
|
|
|
objects = Entity.objects.filter(**filters) |
625
|
|
|
|
626
|
|
|
if objects and 'format' in request.GET.keys(): |
627
|
|
|
return export_query_set(request.GET.get('format'), objects, |
628
|
|
|
'entities_search_result', ('entityid', 'types', 'federations')) |
629
|
|
|
|
630
|
|
|
entities = [] |
631
|
|
|
for entity in objects: |
632
|
|
|
entities.append({ |
633
|
|
|
'entityid': entity.entityid, |
634
|
|
|
'name': entity.name, |
635
|
|
|
'absolute_url': entity.get_absolute_url(), |
636
|
|
|
'types': [unicode(item) for item in entity.types.all()], |
637
|
|
|
'federations': [(unicode(item.name), item.get_absolute_url()) for item in entity.federations.all()], |
638
|
|
|
}) |
639
|
|
|
|
640
|
|
|
return render_to_response('metadataparser/service_search.html', |
641
|
|
|
{'settings': settings, |
642
|
|
|
'searchform': form, |
643
|
|
|
'object_list': entities, |
644
|
|
|
'show_filters': False, |
645
|
|
|
}, context_instance=RequestContext(request)) |
646
|
|
|
|
647
|
|
|
def met_logout(request): |
648
|
|
|
logout(request) |
649
|
|
|
return HttpResponseRedirect(request.GET.get("next", "/")) |
650
|
|
|
|
651
|
|
|
|
652
|
|
|
@profile(name='Search entities') |
653
|
|
|
def search_entities(request): |
654
|
|
|
if request.method == 'POST': |
655
|
|
|
form = SearchEntitiesForm(request.POST) |
656
|
|
|
|
657
|
|
|
if form.is_valid(): |
658
|
|
|
filters = {} |
659
|
|
|
args = () |
660
|
|
|
|
661
|
|
|
entity_type = form.cleaned_data['entity_type'] |
662
|
|
|
if entity_type and entity_type != 'All': |
663
|
|
|
filters['types__name'] = entity_type |
664
|
|
|
|
665
|
|
|
entity_category = form.cleaned_data['entity_category'] |
666
|
|
|
if entity_category and entity_category != 'All': |
667
|
|
|
filters['entity_categories__category_id'] = entity_category |
668
|
|
|
|
669
|
|
|
federations = form.cleaned_data['federations'] |
670
|
|
|
if federations and not 'All' in federations: |
671
|
|
|
q_list = [Q(federations__id=f) for f in federations] |
672
|
|
|
args = (reduce(operator.or_, q_list),) |
673
|
|
|
|
674
|
|
|
entity_id = form.cleaned_data['entityid'] |
675
|
|
|
if entity_id and entity_id != '': |
676
|
|
|
filters['entityid__icontains'] = entity_id |
677
|
|
|
|
678
|
|
|
ob_entities = Entity.objects.all() |
679
|
|
|
if args: |
680
|
|
|
ob_entities = ob_entities.filter(*args) |
681
|
|
|
if filters: |
682
|
|
|
ob_entities = ob_entities.filter(**filters) |
683
|
|
|
|
684
|
|
|
ob_entities = ob_entities.prefetch_related('types', 'federations') |
685
|
|
|
pagination = _paginate_fed(ob_entities, form.cleaned_data['page']) |
686
|
|
|
|
687
|
|
|
entities = [] |
688
|
|
|
for entity in ob_entities: |
689
|
|
|
entities.append({ |
690
|
|
|
'entityid': entity.entityid, |
691
|
|
|
'name': entity.name, |
692
|
|
|
'absolute_url': entity.get_absolute_url(), |
693
|
|
|
'types': [unicode(item) for item in entity.types.all()], |
694
|
|
|
'federations': [(unicode(item.name), item.get_absolute_url()) for item in entity.federations.all()], |
695
|
|
|
}) |
696
|
|
|
|
697
|
|
|
export_format = form.cleaned_data['export_format'] |
698
|
|
|
if export_format: |
699
|
|
|
return export_query_set(export_format, entities, |
700
|
|
|
'entities_search_result', ('entityid', 'types', 'federations')) |
701
|
|
|
|
702
|
|
|
return render_to_response('metadataparser/search_entities.html', |
703
|
|
|
{'settings': settings, |
704
|
|
|
'form': form, |
705
|
|
|
'object_list': entities, |
706
|
|
|
'show_filters': False, |
707
|
|
|
'pagination': pagination, |
708
|
|
|
}, context_instance=RequestContext(request)) |
709
|
|
|
|
710
|
|
|
else: |
711
|
|
|
messages.error(request, _('Please correct the errors indicated' |
712
|
|
|
' below')) |
713
|
|
|
else: |
714
|
|
|
form = SearchEntitiesForm() |
715
|
|
|
|
716
|
|
|
return render_to_response('metadataparser/search_entities.html', |
717
|
|
|
{'form': form}, |
718
|
|
|
context_instance=RequestContext(request)) |
719
|
|
|
|
720
|
|
|
|
721
|
|
|
|