Revision 618d7e05

b/pithos/im/views.py
34 34
import json
35 35
import logging
36 36
import socket
37
import csv
37 38

  
38 39
from datetime import datetime
39 40
from functools import wraps
......
75 76
        return func(request, *args)
76 77
    return wrapper
77 78

  
78

  
79 79
def requires_admin(func):
80 80
    @wraps(func)
81 81
    def wrapper(request, *args):
......
91 91

  
92 92

  
93 93
def index(request):
94
    return render_response('index.html', next=request.GET.get('next', ''))
94
    kwargs = {'standard_modules':settings.IM_STANDARD_MODULES,
95
              'other_modules':settings.IM_OTHER_MODULES}
96
    return render_response('index.html',
97
                           next=request.GET.get('next', ''),
98
                           **kwargs)
95 99

  
96 100

  
97 101
@requires_admin
......
134 138
                            page=page,
135 139
                            prev=prev,
136 140
                            next=next)
137
    
138
@requires_admin
139
def users_create(request):
140
    if request.method == 'GET':
141
        return render_response('users_create.html')
142
    if request.method == 'POST':
143
        user = User()
144
        user.uniq = request.POST.get('uniq')
145
        user.realname = request.POST.get('realname')
146
        user.is_admin = True if request.POST.get('admin') else False
147
        user.affiliation = request.POST.get('affiliation')
148
        user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
149
        user.renew_token()
150
        user.save()
151
        return redirect(users_info, user.id)
152 141

  
153 142
@requires_admin
154 143
def users_info(request, user_id):
......
229 218
                defaults={'code': code, 'realname': realname})
230 219
            
231 220
            try:
232
                send_invitation(request.get_host(), invitation)
221
                send_invitation(request.build_absolute_uri('/').rstrip('/'), invitation)
233 222
                if created:
234 223
                    inviter.invitations = max(0, inviter.invitations - 1)
235 224
                    inviter.save()
......
257 246
    return HttpResponse(html)
258 247

  
259 248
def send_verification(baseurl, user):
260
    next = quote('http://%s' % baseurl)
261 249
    url = settings.ACTIVATION_LOGIN_TARGET % (baseurl,
262 250
                                              quote(user.auth_token),
263
                                              next)
251
                                              quote(baseurl))
264 252
    message = render_to_string('activation.txt', {
265 253
            'user': user,
266 254
            'url': url,
......
309 297
                user.level = 1
310 298
                user.renew_token()
311 299
                try:
312
                    send_verification(request.get_host(), user)
300
                    send_verification(request.build_absolute_uri('/').rstrip('/'), user)
313 301
                    message = _('Verification sent to %s' % user.email)
314 302
                    user.save()
315 303
                except (SMTPException, socket.error) as e:
......
324 312
        return response
325 313

  
326 314
def send_password(baseurl, user):
327
    next = quote('http://%s' % baseurl)
328 315
    url = settings.PASSWORD_RESET_TARGET % (baseurl,
329 316
                                            quote(user.uniq),
330
                                            next)
317
                                            quote(baseurl))
331 318
    message = render_to_string('password.txt', {
332 319
            'user': user,
333 320
            'url': url,
......
347 334
        try:
348 335
            user = User.objects.get(uniq=username)
349 336
            try:
350
                send_password(request.get_host(), user)
337
                send_password(request.build_absolute_uri('/').rstrip('/'), user)
351 338
                status = 'success'
352 339
                message = _('Password reset sent to %s' % user.email)
353 340
                user.status = 'UNVERIFIED'
......
364 351
                'status': status,
365 352
                'message': message})
366 353
        return HttpResponse(html)
354

  
355
@requires_admin
356
def invitations_list(request):
357
    invitations = Invitation.objects.order_by('id')
358
    
359
    filter = request.GET.get('filter', '')
360
    if filter:
361
        if filter.startswith('-'):
362
            invitations = invitations.exclude(uniq__icontains=filter[1:])
363
        else:
364
            invitations = invitations.filter(uniq__icontains=filter)
365
    
366
    try:
367
        page = int(request.GET.get('page', 1))
368
    except ValueError:
369
        page = 1
370
    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
371
    limit = offset + settings.ADMIN_PAGE_LIMIT
372
    
373
    npages = int(ceil(1.0 * invitations.count() / settings.ADMIN_PAGE_LIMIT))
374
    prev = page - 1 if page > 1 else None
375
    next = page + 1 if page < npages else None
376
    return render_response('invitations_list.html',
377
                            invitations=invitations[offset:limit],
378
                            filter=filter,
379
                            pages=range(1, npages + 1),
380
                            page=page,
381
                            prev=prev,
382
                            next=next)
383

  
384
@requires_admin
385
def invitations_export(request):
386
    # Create the HttpResponse object with the appropriate CSV header.
387
    response = HttpResponse(mimetype='text/csv')
388
    response['Content-Disposition'] = 'attachment; filename=invitations.csv'
389

  
390
    writer = csv.writer(response)
391
    writer.writerow(['ID',
392
                     'Uniq',
393
                     'Real Name',
394
                     'Code',
395
                     'Inviter Uniq',
396
                     'Inviter Real Name',
397
                     'Is_accepted',
398
                     'Created',
399
                     'Accepted',])
400
    invitations = Invitation.objects.order_by('id')
401
    for inv in invitations:
402
        writer.writerow([inv.id,
403
                         inv.uniq.encode("utf-8"),
404
                         inv.realname.encode("utf-8"),
405
                         inv.code,
406
                         inv.inviter.uniq.encode("utf-8"),
407
                         inv.inviter.realname.encode("utf-8"),
408
                         inv.is_accepted,
409
                         inv.created,
410
                         inv.accepted])
411

  
412
    return response
413

  
414

  
415
@requires_admin
416
def users_export(request):
417
    # Create the HttpResponse object with the appropriate CSV header.
418
    response = HttpResponse(mimetype='text/csv')
419
    response['Content-Disposition'] = 'attachment; filename=users.csv'
420

  
421
    writer = csv.writer(response)
422
    writer.writerow(['ID',
423
                     'Uniq',
424
                     'Real Name',
425
                     'Admin',
426
                     'Affiliation',
427
                     'State',
428
                     'Quota (GiB)',
429
                     'Updated',])
430
    users = User.objects.order_by('id')
431
    for u in users:
432
        writer.writerow([u.id,
433
                         u.uniq.encode("utf-8"),
434
                         u.realname.encode("utf-8"),
435
                         u.is_admin,
436
                         u.affiliation.encode("utf-8"),
437
                         u.state.encode("utf-8"),
438
                         u.quota,
439
                         u.updated])
440

  
441
    return response
442

  
443
@requires_admin
444
def users_create(request):
445
    if request.method == 'GET':
446
        return render_response('users_create.html')
447
    if request.method == 'POST':
448
        user = User()
449
        user.uniq = request.POST.get('uniq')
450
        user.realname = request.POST.get('realname')
451
        user.is_admin = True if request.POST.get('admin') else False
452
        user.affiliation = request.POST.get('affiliation')
453
        user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
454
        user.renew_token()
455
        user.save()
456
        return redirect(users_info, user.id)
457

  
458
@requires_login
459
def users_profile(request):
460
    next = request.GET.get('next')
461
    user = User.objects.get(uniq=request.user)
462
    states = [x[0] for x in User.ACCOUNT_STATE]
463
    return render_response('users_profile.html',
464
                            user=user,
465
                            states=states,
466
                            next=next)
467

  
468
@requires_login
469
def users_edit(request):
470
    user = User.objects.get(uniq=request.user)
471
    user.realname = request.POST.get('realname')
472
    user.affiliation = request.POST.get('affiliation')
473
    user.is_verified = True
474
    user.save()
475
    next = request.POST.get('next')
476
    if next:
477
        return redirect(next)
478
    
479
    status = 'success'
480
    message = _('Profile has been updated')
481
    html = render_to_string('users_profile.html', {
482
            'user': user,
483
            'status': status,
484
            'message': message})
485
    return HttpResponse(html)
486
    
b/pithos/settings.py.dist
74 74
BACKEND_BLOCK_MODULE = 'pithos.backends.lib.hashfiler'
75 75
BACKEND_BLOCK_PATH = os.path.join(PROJECT_PATH, 'data/')
76 76

  
77

  
78 77
# Bypass authentication for user administration.
79 78
BYPASS_ADMIN_AUTH = False
80 79

  
......
131 130
#    'django.middleware.csrf.CsrfViewMiddleware',
132 131
#    'django.contrib.auth.middleware.AuthenticationMiddleware',
133 132
#    'django.contrib.messages.middleware.MessageMiddleware',
133
    'pithos.middleware.URLEncodedHeadersMiddleware',
134 134
    'pithos.middleware.LoggingConfigMiddleware',
135 135
    'pithos.middleware.AuthMiddleware'
136 136
)
......
153 153
#    'django.contrib.admindocs',
154 154
    'pithos.im',
155 155
    'pithos.api',
156
    'pithos.public',
157
    'pithos.ui'
156
    'pithos.ui',
157
    'south'
158 158
)
159 159

  
160 160
# Set the expiration time of newly created auth tokens
......
187 187
    4   :   0
188 188
}
189 189

  
190
SERVICE_NAME = 'Pithos+'
190
SERVICE_NAME = 'Pithos'
191 191

  
192 192
# Where users should login with their invitation code
193
INVITATION_LOGIN_TARGET = 'http://%s/im/login/invitation' \
193
INVITATION_LOGIN_TARGET = '%s/im/login/invitation' \
194 194
                            '?code=%d' \
195 195
                            '&next=%s'
196 196

  
197 197
# Where users should activate their local account
198
ACTIVATION_LOGIN_TARGET = 'http://%s/im/local/activate/' \
198
ACTIVATION_LOGIN_TARGET = '%s/im/local/activate/' \
199 199
                            '?auth=%s' \
200 200
                            '&next=%s'
201 201

  
202 202
# Where users should reset their local password
203
PASSWORD_RESET_TARGET = 'http://%s/im/local/reset/' \
203
PASSWORD_RESET_TARGET = '%s/im/local/reset/' \
204 204
                            '?username=%s' \
205 205
                            '&next=%s'
206 206

  
207
# Force user profile verification
208
FORCE_PROFILE_UPDATE = False
209

  
207 210
# The server is behind a proy (apache and gunicorn setup).
208 211
USE_X_FORWARDED_HOST = False
209 212

  
213
# Set umask (needed for gunicorn setup).
214
#os.umask(0077)
215

  
210 216
# Use to log to a file.
211 217
LOGFILE = None
218

  
219
# Identity Management enabled modules
220
IM_STANDARD_MODULES = ['local', 'invitation']
221
IM_OTHER_MODULES = ['twitter', 'shibboleth']

Also available in: Unified diff