Revision ae497612

b/snf-astakos-app/astakos/im/activation_backends.py
41 41
from astakos.im.functions import (send_verification, send_activation,
42 42
                                  send_account_creation_notification,
43 43
                                  send_group_creation_notification, activate)
44
from astakos.im.settings import INVITATIONS_ENABLED, MODERATION_ENABLED, SITENAME, RE_USER_EMAIL_PATTERNS
44
from astakos.im.settings import (INVITATIONS_ENABLED, MODERATION_ENABLED,
45
    SITENAME, RE_USER_EMAIL_PATTERNS
46
)
47
from astakos.im.messages import as astakos_messages
45 48

  
46 49
import logging
47 50
import re
......
226 229

  
227 230
class VerificationSent(ActivationResult):
228 231
    def __init__(self):
229
        message = _('Verification sent.')
232
        message = _(astakos_messages.VERIFICATION_SENT)
230 233
        super(VerificationSent, self).__init__(message)
231 234

  
232 235

  
233 236
class SwitchAccountsVerificationSent(ActivationResult):
234 237
    def __init__(self, email):
235
        message = _('This email is already associated with another \
236
                    local account. To change this account to a shibboleth \
237
                    one follow the link in the verification email sent \
238
                    to %s. Otherwise just ignore it.' % email)
238
        message = _(astakos_messages.SWITCH_ACCOUNT_LINK_SENT)
239 239
        super(SwitchAccountsVerificationSent, self).__init__(message)
240 240

  
241 241

  
242 242
class NotificationSent(ActivationResult):
243 243
    def __init__(self):
244
        message = _('Your request for an account was successfully received and is now pending \
245
                    approval. You will be notified by email in the next few days. Thanks for \
246
                    your interest in ~okeanos! The GRNET team.')
244
        message = _(astakos_messages.NOTIFACATION_SENT)
247 245
        super(NotificationSent, self).__init__(message)
248 246

  
249 247

  
250 248
class RegistationCompleted(ActivationResult):
251 249
    def __init__(self):
252
        message = _('Registration completed. You can now login.')
250
        message = _(astakos_messages.REGISTRATION_COMPLETED)
253 251
        super(RegistationCompleted, self).__init__(message)
b/snf-astakos-app/astakos/im/endpoints/quotaholder.py
47 47

  
48 48
ENTITY_KEY = '1'
49 49

  
50
inf = float('inf')
51

  
50 52
logger = logging.getLogger(__name__)
51 53

  
54
inf = float('inf')
52 55

  
53 56
def call(func_name):
54 57
    """Decorator function for QuotaholderHTTP client calls."""
......
88 91
        for resource, uplimit in user.quota.iteritems():
89 92
            key = ENTITY_KEY
90 93
            quantity = None
91
            capacity = uplimit
94
            capacity = uplimit if uplimit != inf else None
92 95
            import_limit = None
93 96
            export_limit = None
94 97
            flags = 0
b/snf-astakos-app/astakos/im/forms.py
60 60

  
61 61
from astakos.im.util import reserved_email, get_query
62 62

  
63
import astakos.im.messages as astakos_messages
64

  
63 65
import logging
64 66
import hashlib
65 67
import recaptcha.client.captcha as captcha
......
116 118
    def clean_email(self):
117 119
        email = self.cleaned_data['email']
118 120
        if not email:
119
            raise forms.ValidationError(_("This field is required"))
121
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
120 122
        if reserved_email(email):
121
            raise forms.ValidationError(_("This email is already used"))
123
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
122 124
        return email
123 125

  
124 126
    def clean_has_signed_terms(self):
125 127
        has_signed_terms = self.cleaned_data['has_signed_terms']
126 128
        if not has_signed_terms:
127
            raise forms.ValidationError(_('You have to agree with the terms'))
129
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
128 130
        return has_signed_terms
129 131

  
130 132
    def clean_recaptcha_response_field(self):
......
142 144
        rrf = self.cleaned_data['recaptcha_response_field']
143 145
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
144 146
        if not check.is_valid:
145
            raise forms.ValidationError(
146
                _('You have not entered the correct words'))
147
            raise forms.ValidationError(_(astakos_messages.CAPTCHA_VALIDATION_ERR))
147 148

  
148 149
    def save(self, commit=True):
149 150
        """
......
222 223
    def clean_email(self):
223 224
        email = self.cleaned_data['email']
224 225
        if not email:
225
            raise forms.ValidationError(_("This field is required"))
226
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
226 227
        return email
227 228

  
228 229
    def clean_has_signed_terms(self):
229 230
        has_signed_terms = self.cleaned_data['has_signed_terms']
230 231
        if not has_signed_terms:
231
            raise forms.ValidationError(_('You have to agree with the terms'))
232
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
232 233
        return has_signed_terms
233 234

  
234 235
    def save(self, commit=True):
......
287 288
        email = self.cleaned_data['email']
288 289
        for user in AstakosUser.objects.filter(email=email):
289 290
            if user.provider == 'shibboleth':
290
                raise forms.ValidationError(_("This email is already associated with another shibboleth account."))
291
                raise forms.ValidationError(_(astakos_messages.SHIBBOLETH_EMAIL_USED))
291 292
            elif not user.is_active:
292
                raise forms.ValidationError(_("This email is already associated with an inactive account. \
293
                                              You need to wait to be activated before being able to switch to a shibboleth account."))
293
                raise forms.ValidationError(_(astakos_messages.SHIBBOLETH_INACTIVE_ACC))
294 294
        super(ShibbolethUserCreationForm, self).clean_email()
295 295
        return email
296 296

  
......
343 343
        rrf = self.cleaned_data['recaptcha_response_field']
344 344
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
345 345
        if not check.is_valid:
346
            raise forms.ValidationError(
347
                _('You have not entered the correct words'))
346
            raise forms.ValidationError(_(astakos_messages.CAPTCHA_VALIDATION_ERR))
348 347

  
349 348
    def clean(self):
350 349
        super(LoginForm, self).clean()
351 350
        if self.user_cache and self.user_cache.provider not in ('local', ''):
352
            raise forms.ValidationError(_('Local login is not the current authentication method for this account.'))
351
            raise forms.ValidationError(_(astakos_messages.SUSPENDED_LOCAL_ACC))
353 352
        return self.cleaned_data
354 353

  
355 354

  
......
419 418
        try:
420 419
            user = AstakosUser.objects.get(email=email, is_active=True)
421 420
            if not user.has_usable_password():
422
                raise forms.ValidationError(
423
                    _("This account has not a usable password."))
421
                raise forms.ValidationError(_(astakos_messages.UNUSABLE_PASSWORD))
424 422
        except AstakosUser.DoesNotExist:
425
            raise forms.ValidationError(_('That e-mail address doesn\'t have an associated user account. Are you sure you\'ve registered?'))
423
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
426 424
        return email
427 425

  
428 426
    def save(
......
460 458
    def clean_new_email_address(self):
461 459
        addr = self.cleaned_data['new_email_address']
462 460
        if AstakosUser.objects.filter(email__iexact=addr):
463
            raise forms.ValidationError(_(u'This email address is already in use. Please supply a different email address.'))
461
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
464 462
        return addr
465 463

  
466 464
    def save(self, email_template_name, request, commit=True):
......
485 483
    def clean_has_signed_terms(self):
486 484
        has_signed_terms = self.cleaned_data['has_signed_terms']
487 485
        if not has_signed_terms:
488
            raise forms.ValidationError(_('You have to agree with the terms'))
486
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
489 487
        return has_signed_terms
490 488

  
491 489

  
......
503 501
        username = self.cleaned_data['username']
504 502
        try:
505 503
            Invitation.objects.get(username=username)
506
            raise forms.ValidationError(
507
                _('There is already invitation for this email.'))
504
            raise forms.ValidationError(_(astakos_messages.INVITATION_EMAIL_EXISTS))
508 505
        except Invitation.DoesNotExist:
509 506
            pass
510 507
        return username
......
690 687
class AddGroupMembersForm(forms.Form):
691 688
    q = forms.CharField(
692 689
        max_length=800, widget=forms.Textarea, label=_('Add users'),
693
        help_text=_('Add comma separated user emails, eg. user1@user.com, user2@user.com'),
690
        help_text=_(astakos_messages.ADD_GROUP_MEMBERS_Q_HELP),
694 691
        required=True)
695 692

  
696 693
    def clean(self):
......
700 697
        db_entries = AstakosUser.objects.filter(email__in=users)
701 698
        unknown = list(set(users) - set(u.email for u in db_entries))
702 699
        if unknown:
703
            raise forms.ValidationError(
704
                _('Unknown users: %s' % ','.join(unknown)))
700
            raise forms.ValidationError(_(astakos_messages.UNKNOWN_USERS) % ','.join(unknown))
705 701
        self.valid_users = db_entries
706 702
        return self.cleaned_data
707 703

  
b/snf-astakos-app/astakos/im/functions.py
61 61
                                 FEEDBACK_EMAIL_SUBJECT,
62 62
                                 EMAIL_CHANGE_EMAIL_SUBJECT)
63 63
import astakos.im.models
64
import astakos.im.messages as astakos_messages
64 65

  
65 66
logger = logging.getLogger(__name__)
66 67

  
......
303 304

  
304 305
class SendAdminNotificationError(SendMailError):
305 306
    def __init__(self):
306
        self.message = _('Failed to send notification')
307
        self.message = _(astakos_messages.ADMIN_NOTIFICATION_SEND_ERR)
307 308
        super(SendAdminNotificationError, self).__init__()
308 309

  
309 310

  
310 311
class SendVerificationError(SendMailError):
311 312
    def __init__(self):
312
        self.message = _('Failed to send verification')
313
        self.message = _(astakos_messages.VERIFICATION_SEND_ERR)
313 314
        super(SendVerificationError, self).__init__()
314 315

  
315 316

  
316 317
class SendInvitationError(SendMailError):
317 318
    def __init__(self):
318
        self.message = _('Failed to send invitation')
319
        self.message = _(astakos_messages.INVITATION_SEND_ERR)
319 320
        super(SendInvitationError, self).__init__()
320 321

  
321 322

  
322 323
class SendGreetingError(SendMailError):
323 324
    def __init__(self):
324
        self.message = _('Failed to send greeting')
325
        self.message = _(astakos_messages.GREETING_SEND_ERR)
325 326
        super(SendGreetingError, self).__init__()
326 327

  
327 328

  
328 329
class SendFeedbackError(SendMailError):
329 330
    def __init__(self):
330
        self.message = _('Failed to send feedback')
331
        self.message = _(astakos_messages.FEEDBACK_SEND_ERR)
331 332
        super(SendFeedbackError, self).__init__()
332 333

  
333 334

  
334 335
class ChangeEmailError(SendMailError):
335 336
    def __init__(self):
336
        self.message = _('Failed to send change email')
337
        self.message = self.message = _(astakos_messages.CHANGE_EMAIL_SEND_ERR)
337 338
        super(ChangeEmailError, self).__init__()
338 339

  
339 340

  
340 341
class SendNotificationError(SendMailError):
341 342
    def __init__(self):
342
        self.message = _('Failed to send notification email')
343
        self.message = _(astakos_messages.NOTIFICATION_SEND_ERR)
343 344
        super(SendNotificationError, self).__init__()
/dev/null
1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
from optparse import make_option
35

  
36
from django.core.management.base import BaseCommand, CommandError
37
from django.contrib.auth.models import Group, Permission
38
from django.contrib.contenttypes.models import ContentType
39
from django.core.exceptions import ValidationError
40

  
41
from astakos.im.models import AstakosUser
42
from ._common import remove_user_permission, add_user_permission
43

  
44

  
45
class Command(BaseCommand):
46
    args = "<user ID>"
47
    help = "Modify a user's attributes"
48

  
49
    option_list = BaseCommand.option_list + (
50
        make_option('--invitations',
51
                    dest='invitations',
52
                    metavar='NUM',
53
                    help="Update user's invitations"),
54
        make_option('--level',
55
                    dest='level',
56
                    metavar='NUM',
57
                    help="Update user's level"),
58
        make_option('--password',
59
                    dest='password',
60
                    metavar='PASSWORD',
61
                    help="Set user's password"),
62
        make_option('--provider',
63
                    dest='provider',
64
                    metavar='PROVIDER',
65
                    help="Set user's provider"),
66
        make_option('--renew-token',
67
                    action='store_true',
68
                    dest='renew_token',
69
                    default=False,
70
                    help="Renew the user's token"),
71
        make_option('--renew-password',
72
                    action='store_true',
73
                    dest='renew_password',
74
                    default=False,
75
                    help="Renew the user's password"),
76
        make_option('--set-admin',
77
                    action='store_true',
78
                    dest='admin',
79
                    default=False,
80
                    help="Give user admin rights"),
81
        make_option('--set-noadmin',
82
                    action='store_true',
83
                    dest='noadmin',
84
                    default=False,
85
                    help="Revoke user's admin rights"),
86
        make_option('--set-active',
87
                    action='store_true',
88
                    dest='active',
89
                    default=False,
90
                    help="Change user's state to inactive"),
91
        make_option('--set-inactive',
92
                    action='store_true',
93
                    dest='inactive',
94
                    default=False,
95
                    help="Change user's state to inactive"),
96
        make_option('--add-group',
97
                    dest='add-group',
98
                    help="Add user group"),
99
        make_option('--delete-group',
100
                    dest='delete-group',
101
                    help="Delete user group"),
102
        make_option('--add-permission',
103
                    dest='add-permission',
104
                    help="Add user permission"),
105
        make_option('--delete-permission',
106
                    dest='delete-permission',
107
                    help="Delete user permission"),
108
    )
109

  
110
    def handle(self, *args, **options):
111
        if len(args) != 1:
112
            raise CommandError("Please provide a user ID")
113

  
114
        if args[0].isdigit():
115
            user = AstakosUser.objects.get(id=int(args[0]))
116
        else:
117
            raise CommandError("Invalid ID")
118

  
119
        if not user:
120
            raise CommandError("Unknown user")
121

  
122
        if options.get('admin'):
123
            user.is_superuser = True
124
        elif options.get('noadmin'):
125
            user.is_superuser = False
126

  
127
        if options.get('active'):
128
            user.is_active = True
129
        elif options.get('inactive'):
130
            user.is_active = False
131

  
132
        invitations = options.get('invitations')
133
        if invitations is not None:
134
            user.invitations = int(invitations)
135

  
136
        groupname = options.get('add-group')
137
        if groupname is not None:
138
            try:
139
                group = Group.objects.get(name=groupname)
140
                user.groups.add(group)
141
            except Group.DoesNotExist, e:
142
                self.stdout.write(
143
                    "Group named %s does not exist\n" % groupname)
144

  
145
        groupname = options.get('delete-group')
146
        if groupname is not None:
147
            try:
148
                group = Group.objects.get(name=groupname)
149
                user.groups.remove(group)
150
            except Group.DoesNotExist, e:
151
                self.stdout.write(
152
                    "Group named %s does not exist\n" % groupname)
153

  
154
        pname = options.get('add-permission')
155
        if pname is not None:
156
            try:
157
                r, created = add_user_permission(user, pname)
158
                if created:
159
                    self.stdout.write(
160
                        'Permission: %s created successfully\n' % pname)
161
                if r > 0:
162
                    self.stdout.write(
163
                        'Permission: %s added successfully\n' % pname)
164
                elif r == 0:
165
                    self.stdout.write(
166
                        'User has already permission: %s\n' % pname)
167
            except Exception, e:
168
                raise CommandError(e)
169

  
170
        pname = options.get('delete-permission')
171
        if pname is not None and not user.has_perm(pname):
172
            try:
173
                r = remove_user_permission(user, pname)
174
                if r < 0:
175
                    self.stdout.write(
176
                        'Invalid permission codename: %s\n' % pname)
177
                elif r == 0:
178
                    self.stdout.write('User has not permission: %s\n' % pname)
179
                elif r > 0:
180
                    self.stdout.write(
181
                        'Permission: %s removed successfully\n' % pname)
182
            except Exception, e:
183
                raise CommandError(e)
184

  
185
        level = options.get('level')
186
        if level is not None:
187
            user.level = int(level)
188

  
189
        password = options.get('password')
190
        if password is not None:
191
            user.set_password(password)
192

  
193
        provider = options.get('provider')
194
        if provider is not None:
195
            user.provider = provider
196

  
197
        password = None
198
        if options['renew_password']:
199
            password = AstakosUser.objects.make_random_password()
200
            user.set_password(password)
201

  
202
        if options['renew_token']:
203
            user.renew_token()
204

  
205
        try:
206
            user.save()
207
        except ValidationError, e:
208
            raise CommandError(e)
209

  
210
        if password:
211
            self.stdout.write('User\'s new password: %s\n' % password)
b/snf-astakos-app/astakos/im/management/commands/user-update.py
1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
from optparse import make_option
35

  
36
from django.core.management.base import BaseCommand, CommandError
37
from django.contrib.auth.models import Group, Permission
38
from django.contrib.contenttypes.models import ContentType
39
from django.core.exceptions import ValidationError
40

  
41
from astakos.im.models import AstakosUser
42
from ._common import remove_user_permission, add_user_permission
43

  
44

  
45
class Command(BaseCommand):
46
    args = "<user ID>"
47
    help = "Modify a user's attributes"
48

  
49
    option_list = BaseCommand.option_list + (
50
        make_option('--invitations',
51
                    dest='invitations',
52
                    metavar='NUM',
53
                    help="Update user's invitations"),
54
        make_option('--level',
55
                    dest='level',
56
                    metavar='NUM',
57
                    help="Update user's level"),
58
        make_option('--password',
59
                    dest='password',
60
                    metavar='PASSWORD',
61
                    help="Set user's password"),
62
        make_option('--provider',
63
                    dest='provider',
64
                    metavar='PROVIDER',
65
                    help="Set user's provider"),
66
        make_option('--renew-token',
67
                    action='store_true',
68
                    dest='renew_token',
69
                    default=False,
70
                    help="Renew the user's token"),
71
        make_option('--renew-password',
72
                    action='store_true',
73
                    dest='renew_password',
74
                    default=False,
75
                    help="Renew the user's password"),
76
        make_option('--set-admin',
77
                    action='store_true',
78
                    dest='admin',
79
                    default=False,
80
                    help="Give user admin rights"),
81
        make_option('--set-noadmin',
82
                    action='store_true',
83
                    dest='noadmin',
84
                    default=False,
85
                    help="Revoke user's admin rights"),
86
        make_option('--set-active',
87
                    action='store_true',
88
                    dest='active',
89
                    default=False,
90
                    help="Change user's state to inactive"),
91
        make_option('--set-inactive',
92
                    action='store_true',
93
                    dest='inactive',
94
                    default=False,
95
                    help="Change user's state to inactive"),
96
        make_option('--add-group',
97
                    dest='add-group',
98
                    help="Add user group"),
99
        make_option('--delete-group',
100
                    dest='delete-group',
101
                    help="Delete user group"),
102
        make_option('--add-permission',
103
                    dest='add-permission',
104
                    help="Add user permission"),
105
        make_option('--delete-permission',
106
                    dest='delete-permission',
107
                    help="Delete user permission"),
108
    )
109

  
110
    def handle(self, *args, **options):
111
        if len(args) != 1:
112
            raise CommandError("Please provide a user ID")
113

  
114
        if args[0].isdigit():
115
            user = AstakosUser.objects.get(id=int(args[0]))
116
        else:
117
            raise CommandError("Invalid ID")
118

  
119
        if not user:
120
            raise CommandError("Unknown user")
121

  
122
        if options.get('admin'):
123
            user.is_superuser = True
124
        elif options.get('noadmin'):
125
            user.is_superuser = False
126

  
127
        if options.get('active'):
128
            user.is_active = True
129
        elif options.get('inactive'):
130
            user.is_active = False
131

  
132
        invitations = options.get('invitations')
133
        if invitations is not None:
134
            user.invitations = int(invitations)
135

  
136
        groupname = options.get('add-group')
137
        if groupname is not None:
138
            try:
139
                group = Group.objects.get(name=groupname)
140
                user.groups.add(group)
141
            except Group.DoesNotExist, e:
142
                self.stdout.write(
143
                    "Group named %s does not exist\n" % groupname)
144

  
145
        groupname = options.get('delete-group')
146
        if groupname is not None:
147
            try:
148
                group = Group.objects.get(name=groupname)
149
                user.groups.remove(group)
150
            except Group.DoesNotExist, e:
151
                self.stdout.write(
152
                    "Group named %s does not exist\n" % groupname)
153

  
154
        pname = options.get('add-permission')
155
        if pname is not None:
156
            try:
157
                r, created = add_user_permission(user, pname)
158
                if created:
159
                    self.stdout.write(
160
                        'Permission: %s created successfully\n' % pname)
161
                if r > 0:
162
                    self.stdout.write(
163
                        'Permission: %s added successfully\n' % pname)
164
                elif r == 0:
165
                    self.stdout.write(
166
                        'User has already permission: %s\n' % pname)
167
            except Exception, e:
168
                raise CommandError(e)
169

  
170
        pname = options.get('delete-permission')
171
        if pname is not None and not user.has_perm(pname):
172
            try:
173
                r = remove_user_permission(user, pname)
174
                if r < 0:
175
                    self.stdout.write(
176
                        'Invalid permission codename: %s\n' % pname)
177
                elif r == 0:
178
                    self.stdout.write('User has not permission: %s\n' % pname)
179
                elif r > 0:
180
                    self.stdout.write(
181
                        'Permission: %s removed successfully\n' % pname)
182
            except Exception, e:
183
                raise CommandError(e)
184

  
185
        level = options.get('level')
186
        if level is not None:
187
            user.level = int(level)
188

  
189
        password = options.get('password')
190
        if password is not None:
191
            user.set_password(password)
192

  
193
        provider = options.get('provider')
194
        if provider is not None:
195
            user.provider = provider
196

  
197
        password = None
198
        if options['renew_password']:
199
            password = AstakosUser.objects.make_random_password()
200
            user.set_password(password)
201

  
202
        if options['renew_token']:
203
            user.renew_token()
204

  
205
        try:
206
            user.save()
207
        except ValidationError, e:
208
            raise CommandError(e)
209

  
210
        if password:
211
            self.stdout.write('User\'s new password: %s\n' % password)
b/snf-astakos-app/astakos/im/messages.py
1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
ACCOUNT_AUTHENTICATION_FAILED           =   'Cannot authenticate account.'
35
ACCOUNT_INACTIVE                        =   'Inactive account.'
36
ACCOUNT_ALREADY_ACTIVE                  =   'Account is already active.'
37
TOKEN_UNKNOWN                           =   'There is no user matching this token.'
38

  
39
INVITATION_SENT                         =   'Invitation sent to %(emails.'
40
PROFILE_UPDATED                         =   'Profile has been updated successfully.'
41
FEEDBACK_SENT                           =   'Feedback successfully sent.'
42
EMAIL_CHANGED                           =   'Account email has been changed successfully.'
43
EMAIL_CHANGE_REGISTERED                 =   'Change email request has been registered succefully. \
44
                                               You are going to receive a verification email in the new address.'
45

  
46
OBJECT_CREATED                          =   'The %(verbose_names was created successfully.'
47
MEMBER_JOINED_GROUP                     =   '%(realnames has been successfully joined the group.'
48
MEMBER_REMOVED                          =   '%(realnames has been successfully removed from the group.'
49
BILLING_ERROR                           =   'Service response status: %(status)d' 
50
LOGOUT_SUCCESS                          =   'You have successfully logged out.'
51

  
52
GENERIC_ERROR                           =   'Something wrong has happened. \
53
                                               Please contact the administrators for more details.'
54

  
55
MAX_INVITATION_NUMBER_REACHED   =           'There are no invitations left.'
56
GROUP_MAX_PARTICIPANT_NUMBER_REACHED    =   'Group maximum participant number has been reached.'
57
NO_APPROVAL_TERMS                       =   'There are no approval terms.'
58
PENDING_EMAIL_CHANGE_REQUEST            =   'There is already a pending change email request.'
59
OBJECT_CREATED_FAILED                   =   'The %(verbose_names creation failed: %(reasons.'
60
GROUP_JOIN_FAILURE                      =   'Failed to join group.'
61
GROUPKIND_UNKNOWN                       =   'There is no such a group kind'
62
NOT_MEMBER                              =   'User is not member of the group.'
63
NOT_OWNER                               =   'User is not a group owner.'
64
OWNER_CANNOT_LEAVE_GROUP                =   'Owner cannot leave the group.'
65

  
66
# Field validation fields
67
REQUIRED_FIELD                          =   'This field is required.'
68
EMAIL_USED                              =   'This email address is already in use. Please supply a different email address.'
69
SHIBBOLETH_EMAIL_USED                   =   'This email is already associated with another shibboleth account.'
70
SHIBBOLETH_INACTIVE_ACC                 =   'This email is already associated with an inactive account. \
71
                                               You need to wait to be activated before being able to switch to a shibboleth account.'   
72

  
73
SIGN_TERMS                              =   'You have to agree with the terms.'
74
CAPTCHA_VALIDATION_ERR                  =   'You have not entered the correct words.'
75
SUSPENDED_LOCAL_ACC                     =   'Local login is not the current authentication method for this account.'
76
UNUSABLE_PASSWORD                       =   'This account has not a usable password.'
77
EMAIL_UNKNOWN                           =   'That e-mail address doesn\'t have an associated user account. \
78
                                               Are you sure you\'ve registered?'
79
INVITATION_EMAIL_EXISTS                 =   'There is already invitation for this email.'
80
INVITATION_CONSUMED_ERR                 =   'Invitation is used.'
81
UNKNOWN_USERS                           =   'Unknown users: %s'
82
UNIQUE_EMAIL_IS_ACTIVE_CONSTRAIN_ERR    =   'Another account with the same email & is_active combination found.'
83
INVALID_ACTIVATION_KEY                  =   'Invalid activation key.'
84
NEW_EMAIL_ADDR_RESERVED                 =   'The new email address is reserved.'
85
EMAIL_RESERVED                          =   'Email: %(email)s is reserved'
86

  
87
# Field help text
88
ADD_GROUP_MEMBERS_Q_HELP                =   'Add comma separated user emails, eg. user1@user.com, user2@user.com'
89
ASTAKOSUSER_GROUPS_HELP                 =   'In addition to the permissions manually assigned, \
90
                                               this user will also get all permissions granted to each group he/she is in.'
91
EMAIL_CHANGE_NEW_ADDR_HELP              =   'Your old email address will be used until you verify your new one.'
92

  
93
EMAIL_SEND_ERR                          =   'Failed to send %s.'
94
ADMIN_NOTIFICATION_SEND_ERR             =   EMAIL_SEND_ERR % 'admin notification'
95
VERIFICATION_SEND_ERR                   =   EMAIL_SEND_ERR % 'verification'
96
INVITATION_SEND_ERR                     =   EMAIL_SEND_ERR % 'invitation'
97
GREETING_SEND_ERR                       =   EMAIL_SEND_ERR % 'greeting'
98
FEEDBACK_SEND_ERR                       =   EMAIL_SEND_ERR % 'feedback'
99
CHANGE_EMAIL_SEND_ERR                   =   EMAIL_SEND_ERR % 'feedback'
100
NOTIFICATION_SEND_ERR                   =   EMAIL_SEND_ERR % 'notification'
101

  
102

  
103
MISSING_NEXT_PARAMETER                  =   'No next parameter'
104

  
105
VERIFICATION_SENT                       =   'Verification sent.'
106

  
107
SWITCH_ACCOUNT_LINK_SENT                =   'This email is already associated with another local account. \
108
                                               To change this account to a shibboleth one follow the link in the verification email sent to %(emails. \
109
                                               Otherwise just ignore it.'
110
NOTIFACATION_SENT                       =   'Your request for an account was successfully received and is now pending approval. \
111
                                               You will be notified by email in the next few days. \
112
                                               Thanks for your interest in ~okeanos! The GRNET team.'
113
REGISTRATION_COMPLETED                  =   'Registration completed. You can now login.'
b/snf-astakos-app/astakos/im/models.py
44 44
from django.db import models, IntegrityError
45 45
from django.contrib.auth.models import User, UserManager, Group, Permission
46 46
from django.utils.translation import ugettext as _
47
from django.db import transaction
47 48
from django.core.exceptions import ValidationError
48 49
from django.db import transaction
49 50
from django.db.models.signals import (pre_save, post_save, post_syncdb,
......
63 64
from astakos.im.tasks import propagate_groupmembers_quota
64 65
from astakos.im.functions import send_invitation
65 66

  
67
import astakos.im.messages as astakos_messages
68

  
66 69
logger = logging.getLogger(__name__)
67 70

  
68 71
DEFAULT_CONTENT_TYPE = None
......
228 231
        self.save()
229 232
        quota_disturbed.send(sender=self, users=self.approved_members)
230 233

  
234
    @transaction.commit_manually
231 235
    def approve_member(self, person):
232 236
        m, created = self.membership_set.get_or_create(person=person)
233 237
        # update date_joined in any case
234
        m.date_joined = datetime.now()
235
        m.save()
238
        try:
239
            m.approve()
240
        except:
241
            transaction.rollback()
242
            raise
243
        else:
244
            transaction.commit()
236 245

  
237
    def disapprove_member(self, person):
238
        self.membership_set.remove(person=person)
246
#     def disapprove_member(self, person):
247
#         self.membership_set.remove(person=person)
239 248

  
240 249
    @property
241 250
    def members(self):
......
340 349

  
341 350
    astakos_groups = models.ManyToManyField(
342 351
        AstakosGroup, verbose_name=_('agroups'), blank=True,
343
        help_text=_("""In addition to the permissions manually assigned, this
344
                    user will also get all permissions granted to each group
345
                    he/she is in."""),
352
        help_text=_(astakos_messages.ASTAKOSUSER_GROUPS_HELP),
346 353
        through='Membership')
347 354

  
348 355
    __has_signed_terms = False
......
519 526
        q = q.filter(email=self.email)
520 527
        q = q.filter(is_active=self.is_active)
521 528
        if q.count() != 0:
522
            raise ValidationError({'__all__': [_('Another account with the same email & is_active combination found.')]})
529
            raise ValidationError({'__all__': [_(astakos_messages.UNIQUE_EMAIL_IS_ACTIVE_CONSTRAIN_ERR)]})
523 530

  
524 531
    @property
525 532
    def signed_terms(self):
......
564 571
        return False
565 572

  
566 573
    def approve(self):
574
        if self.group.max_participants:
575
            assert len(self.group.approved_members) + 1 <= self.group.max_participants
567 576
        self.date_joined = datetime.now()
568 577
        self.save()
569 578
        quota_disturbed.send(sender=self, users=(self.person,))
......
690 699
            except AstakosUser.DoesNotExist:
691 700
                pass
692 701
            else:
693
                raise ValueError(_('The new email address is reserved.'))
702
                raise ValueError(_(astakos_messages.NEW_EMAIL_ADDR_RESERVED))
694 703
            # update user
695 704
            user = AstakosUser.objects.get(pk=email_change.user_id)
696 705
            user.email = email_change.new_email_address
......
698 707
            email_change.delete()
699 708
            return user
700 709
        except EmailChange.DoesNotExist:
701
            raise ValueError(_('Invalid activation key'))
710
            raise ValueError(_(astakos_messages.INVALID_ACTIVATION_KEY))
702 711

  
703 712

  
704 713
class EmailChange(models.Model):
705 714
    new_email_address = models.EmailField(_(u'new e-mail address'),
706
                                          help_text=_(u'Your old email address will be used until you verify your new one.'))
715
                                          help_text=_(astakos_messages.EMAIL_CHANGE_NEW_ADDR_HELP))
707 716
    user = models.ForeignKey(
708 717
        AstakosUser, unique=True, related_name='emailchange_user')
709 718
    requested_at = models.DateTimeField(default=datetime.now())
......
851 860
post_save.connect(send_quota_disturbed, sender=AstakosUserQuota)
852 861
post_delete.connect(send_quota_disturbed, sender=AstakosUserQuota)
853 862
post_save.connect(send_quota_disturbed, sender=AstakosGroupQuota)
854
post_delete.connect(send_quota_disturbed, sender=AstakosGroupQuota)
863
post_delete.connect(send_quota_disturbed, sender=AstakosGroupQuota)
b/snf-astakos-app/astakos/im/target/local.py
43 43
from astakos.im.forms import LoginForm
44 44
from astakos.im.settings import RATELIMIT_RETRIES_ALLOWED
45 45

  
46
import astakos.im.messages as astakos_messages
47

  
46 48
from ratelimit.decorators import ratelimit
47 49

  
48 50
retries = RATELIMIT_RETRIES_ALLOWED - 1
......
72 74

  
73 75
    message = None
74 76
    if not user:
75
        message = _('Cannot authenticate account')
77
        message = _(astakos_messages.ACCOUNT_AUTHENTICATION_FAILED)
76 78
    elif not user.is_active:
77
        message = _('Inactive account')
79
        message = _(astakos_messages.ACCOUNT_INACTIVE)
78 80
    if message:
79 81
        messages.error(request, message)
80 82
        return render_to_response(on_failure,
b/snf-astakos-app/astakos/im/target/redirect.py
45 45
from astakos.im.util import set_cookie
46 46
from astakos.im.functions import login as auth_login, logout
47 47

  
48
import astakos.im.messages as astakos_messages
49

  
48 50
import logging
49 51

  
50 52
logger = logging.getLogger(__name__)
......
62 64
    """
63 65
    next = request.GET.get('next')
64 66
    if not next:
65
        return HttpResponseBadRequest(_('No next parameter'))
67
        return HttpResponseBadRequest(_(astakos_messages.MISSING_NEXT_PARAMETER))
66 68
    force = request.GET.get('force', None)
67 69
    response = HttpResponse()
68 70
    if force == '':
b/snf-astakos-app/astakos/im/target/shibboleth.py
43 43
from astakos.im.forms import LoginForm
44 44
from astakos.im.activation_backends import get_backend, SimpleBackend
45 45

  
46
import astakos.im.messages as astakos_messages
46 47

  
47 48
class Tokens:
48 49
    # these are mapped by the Shibboleth SP software
......
89 90
                                    request.GET.get('next'),
90 91
                                    'renew' in request.GET)
91 92
        else:
92
            message = _('Inactive account')
93
            message = _(astakos_messages.ACCOUNT_INACTIVE)
93 94
            messages.error(request, message)
94 95
            return render_response(on_login_template,
95 96
                                   login_form=LoginForm(request=request),
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
75 75
                    {% endif %}
76 76
                {% endfor %}&nbsp;
77 77
            </dd>
78
            <dt>Max participants</dt>
79
		 	<dd>{% if object.max_participants%}{{object.max_participants}}{% else %}&nbsp;{% endif %}</dd>
78 80
		 </dl>
79 81
	 </div>
80 82
	 
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form.html
1 1
{% extends "im/account_base.html" %}
2 2

  
3
{% load filters %}
4
{% block headjs %}
5
	{{ block.super }}	 
6
	<script src="{{ IM_STATIC_URL }}js/quotas.js"></script>	
7
{% endblock %}	
3 8
{% block page.body %}
4
<div class="projects">
5
	<div class="maincol {% block innerpage.class %}{% endblock %}">
6
	    <form action="" method="post"
7
	            class="withlabels">{% csrf_token %}
8
	          <h2><span>CREATE {{ kind|upper }}</span></h2>
9
	            {% include "im/form_render.html" %}
10
	            <div class="form-row submit">
11
	                <input type="submit" class="submit altcol" value="SUBMIT" />
12
	            </div>
13
	    </form>
9
 
10
	
11
<form action="" method="post" class="withlabels quotas-form">{% csrf_token %}
12
	 
13
    <fieldset class="with-info">
14
    	<legend>
15
    		1. CREATE GROUP
16
			<span class="info"> 
17
		    	<em>more info</em>
18
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
19
	    	</span>    		
20
    	</legend>
21
        
22
        {% include "im/form_render.html" %}
23
		
24
<!-- 
25
		<div class="double-checks">
26
    		<label>Max users per group</label>
27
    		<div class="form-row">
28
    			<p class="clearfix">
29
    				<label for="members_unlimited">Unlimited</label>
30
    				<input type="checkbox" id="members_unlimited" name="members_unlimited" class="unlimited" checked="checked">
31
    				<span class="info"> 
32
				    	<em>more info</em>
33
				    	<span>Help Text Help Text Help Text Text Help Text Help Text</span>
34
			    	</span>  
35
    			</p>
36
    		</div>
37
    		<div class="form-row">
38
    			<p class="clearfix">
39
    				<label for="members_limited">Limited</label>
40
    				<input type="checkbox" id="members_limited" name="members_limited" class="limited">
41
       				<input type="text" id="members_uplimit" name="members_uplimit" />
42
	       			  		 
43
    			</p>
44
    			
45
    		</div>
46
    		
47
    	</div> 
48
 -->
49
    </fieldset>     
50
    
51
    <fieldset id="icons">
52
    	<legend>
53
    		2. CHOOSE RESOURCES
54
    		<span class="info"> 
55
		    	<em>more info</em>
56
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
57
	    	</span>    
58
    	</legend>
59

  
60
    {% with resource_catalog|lookup:'resources' as resources %}
61
    {% with resource_catalog|lookup:'groups' as groups %}    	
62
    	<ul class="clearfix">
63
            {% for g, rs in groups.items %}   
64
            {% with resource_presentation|lookup:g as group_info %} 		
65
    		<li>
66
    			<a href="#{{ g }}" id="{{'group_'|add:g}}"><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
67
    			<input type="hidden" name="{{ 'is_selected_'|add:g }}"  id="{{ 'id_is_selected_'|add:g }}" value="0">
68
    			<p class="msg">{{ group_info.help_text }}</p>
69
    		</li>
70
    		{% endwith %}
71
            {% endfor %}
72
    	</ul>
73
    	
74
    </fieldset>
75
   
76
    <div class="foo">
77
    
78
    </div>
79
    <div class="not-foo">
80
        {% for g, rs in groups.items %}
81
        
82
        <div class="group {{'group_'|add:g}}" id="{{ g }}">
83
			<a href="#icons" class="delete">X remove resource</a>	
84
		    {% for r in rs %}
85
		    {% with resource_presentation|lookup:r as resource_info %}
86
		    {% with resources|lookup:r as resource%}
87
		    <fieldset class="quota storage">
88
		    	<legend>
89
		    		{% if resource_info.is_abbreviation %}
90
		    			{{ r|get_value_after_dot|upper }}
91
		    		{% else %}
92
		    			{{ r|get_value_after_dot|capfirst }}
93
		    		{% endif %}
94
		    		<span class="info"> 
95
				    	<em>more info</em>
96
				    	<span>{{ resource_info.help_text }}</span>
97
			    	</span>  
98
		    	</legend>
99
<!--	    	<div class="form-row">
100
		    		<p class="clearfix">
101
		    			<label for="num_storage">Total storage</label>
102
		    			<input type="text" name="num_storage">
103
		    			<span class="extra-img">&nbsp;</span>
104
		         		<span class="info"><em>more info</em><span>Help Text</span></span>
105
		    		</p>
106
		    	</div>-->
107
 				<div class="double-checks">
108
		    		<label>
109
		    			Max {% if resource_info.is_abbreviation %}{{ r|get_value_after_dot|upper }}{% else %}{{ r|get_value_after_dot }}{% endif %}{% if not resource.unit %}s {% endif  %} per user
110
						{% if resource.unit %} 
111
						 	({{ resource.unit }})
112
						{% endif  %}
113
					</label>
114
		    		<div class="form-row">
115
		    			<p class="clearfix">
116
		    				<label for="{{r|add:'_unlimited'}}">Unlimited</label>
117
		    				<input type="checkbox" id="{{'id_'|add:r|add:'_unlimited'}}" name="{{r|add:'_unlimited'}}" class="unlimited radio" checked="checked">
118
		    			</p>
119
		    		</div>
120
		    		<div class="form-row">
121
		    			<p class="clearfix">
122
		    				<label for="{{r|add:'_limited'}}">Limited</label>
123
		    				<input type="checkbox" id="id_storage_per_user_limited" name="{{r|add:'_limited'}}" class="radio limited">
124
		       				<input type="text" id="{{'id_'|add:r|add:'_uplimit'}}" name="{{r|add:'_uplimit'}}"/> 
125
		    			</p>
126
		    		</div>
127
		    		
128
		    	</div> 
129
		    </fieldset>
130
		    {% endwith %}
131
		    {% endwith %}
132
		    {% endfor %}
133
	    </div>
134
	    
135
    	{% endfor %}
14 136
	</div>
15
</div>
16
{% endblock %}
137
    {% endwith %}
138
    {% endwith %}
139
	 
140
    <div class="form-row submit">
141
   		<input type="submit" value="SUBMIT" class="submit altcol" autocomplete="off">
142
	</div>     
143
</form>
144
	 
145
<script>
146
	
147
</script>	 
148
 
149
{% endblock %}
/dev/null
1
{% extends "im/account_base.html" %}
2

  
3
{% load filters %}
4
{% block headjs %}
5
	{{ block.super }}	 
6
	<script src="{{ IM_STATIC_URL }}js/quotas.js"></script>	
7
{% endblock %}	
8
{% block page.body %}
9
 
10
	
11
<form action="" method="post" class="withlabels quotas-form">{% csrf_token %}
12
	 
13
    <fieldset class="with-info">
14
    	<legend>
15
    		1. CREATE GROUP
16
			<span class="info"> 
17
		    	<em>more info</em>
18
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
19
	    	</span>    		
20
    	</legend>
21
        
22
        {% include "im/form_render.html" %}
23
		
24
<!-- 
25
		<div class="double-checks">
26
    		<label>Max users per group</label>
27
    		<div class="form-row">
28
    			<p class="clearfix">
29
    				<label for="members_unlimited">Unlimited</label>
30
    				<input type="checkbox" id="members_unlimited" name="members_unlimited" class="unlimited" checked="checked">
31
    				<span class="info"> 
32
				    	<em>more info</em>
33
				    	<span>Help Text Help Text Help Text Text Help Text Help Text</span>
34
			    	</span>  
35
    			</p>
36
    		</div>
37
    		<div class="form-row">
38
    			<p class="clearfix">
39
    				<label for="members_limited">Limited</label>
40
    				<input type="checkbox" id="members_limited" name="members_limited" class="limited">
41
       				<input type="text" id="members_uplimit" name="members_uplimit" />
42
	       			  		 
43
    			</p>
44
    			
45
    		</div>
46
    		
47
    	</div> 
48
 -->
49
    </fieldset>     
50
    
51
    <fieldset id="icons">
52
    	<legend>
53
    		2. CHOOSE RESOURCES
54
    		<span class="info"> 
55
		    	<em>more info</em>
56
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
57
	    	</span>    
58
    	</legend>
59

  
60
    {% with resource_catalog|lookup:'resources' as resources %}
61
    {% with resource_catalog|lookup:'groups' as groups %}    	
62
    	<ul class="clearfix">
63
            {% for g, rs in groups.items %}   
64
            {% with resource_presentation|lookup:g as group_info %} 		
65
    		<li>
66
    			<a href="#{{ g }}" id="{{'group_'|add:g}}"><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
67
    			<input type="hidden" name="{{ 'is_selected_'|add:g }}"  id="{{ 'id_is_selected_'|add:g }}" value="0">
68
    			<p class="msg">{{ group_info.help_text }}</p>
69
    		</li>
70
    		{% endwith %}
71
            {% endfor %}
72
    	</ul>
73
    	
74
    </fieldset>
75
   
76
    <div class="foo">
77
    
78
    </div>
79
    <div class="not-foo">
80
        {% for g, rs in groups.items %}
81
        
82
        <div class="group {{'group_'|add:g}}" id="{{ g }}">
83
			<a href="#icons" class="delete">X remove resource</a>	
84
		    {% for r in rs %}
85
		    {% with resource_presentation|lookup:r as resource_info %}
86
		    {% with resources|lookup:r as resource%}
87
		    <fieldset class="quota">
88
		    	<legend>
89
		    		{% if resource_info.is_abbreviation %}
90
		    			{{ r|get_value_after_dot|upper }}
91
		    		{% else %}
92
		    			{{ r|get_value_after_dot|capfirst }}
93
		    		{% endif %}
94
		    		<span class="info"> 
95
				    	<em>more info</em>
96
				    	<span>{{ resource_info.help_text }}</span>
97
			    	</span>  
98
		    	</legend>
99
<!--	    	<div class="form-row">
100
		    		<p class="clearfix">
101
		    			<label for="num_storage">Total storage</label>
102
		    			<input type="text" name="num_storage">
103
		    			<span class="extra-img">&nbsp;</span>
104
		         		<span class="info"><em>more info</em><span>Help Text</span></span>
105
		    		</p>
106
		    	</div>-->
107
 				<!--
108
 				<div class="double-checks">
109
		    		<label>
110
		    			Max {% if resource_info.is_abbreviation %}{{ r|get_value_after_dot|upper }}{% else %}{{ r|get_value_after_dot }}{% endif %}{% if not resource.unit %}s {% endif  %} per user
111
						{% if resource.unit %} 
112
						 	({{ resource.unit }})
113
						{% endif  %}
114
					</label>
115
		    		<div class="form-row">
116
		    			<p class="clearfix">
117
		    				<label for="{{r|add:'_unlimited'}}">Unlimited</label>
118
		    				<input type="checkbox" id="{{'id_'|add:r|add:'_unlimited'}}" name="{{r|add:'_unlimited'}}_proxy" class="unlimited radio" checked="checked">
119
		    			</p>
120
		    		</div>
121
		    		<div class="form-row">
122
		    			<p class="clearfix">
123
		    				<label for="{{r|add:'_limited'}}">Limited</label>
124
		    				<input type="checkbox" id="id_storage_per_user_limited" name="{{r|add:'_limited'}}_proxy" class="radio limited">
125
		       				<input 	type="text" 
126
		       						id="{{'id_'|add:r|add:'_uplimit'}}" 
127
		       						name="{{r|add:'_uplimit'}}_proxy" 
128
		       						placeholder="{{ resource_info.placeholder}} " 
129
		       						{% if resource.unit == 'bytes' %} 
130
									 	class="dehumanize"
131
									{% endif  %}
132
		       						/> 
133
		    			</p>
134
		    			<p class="msg"></p>
135
		    		</div>
136
		    		
137
		    	</div>
138
		    	-->
139
		    	<div class="form-row">
140
		    		<p class="clearfix">
141
		    			<label for="num_storage">
142
							Max {% if resource_info.is_abbreviation %}{{ r|get_value_after_dot|upper }}{% else %}{{ r|get_value_after_dot }}{% endif %}{% if not resource.unit %}s {% endif  %} per user
143
						</label>
144
		    			<input 	type="text" 
145
		       						id="{{'id_'|add:r|add:'_uplimit'}}_proxy" 
146
		       						name="{{r|add:'_uplimit'}}_proxy" 
147
		       						placeholder="{{ resource_info.placeholder}} " 
148
		       						{% if resource.unit == 'bytes' %} 
149
									 	class="dehumanize"
150
									{% endif  %}
151
		       						/> 
152
		    			<span class="extra-img">&nbsp;</span>
153
		         		<span class="info"><em>more info</em><span>Help Text</span></span>
154
		    		</p>
155
		    		<p class="msg"></p>
156
		    	</div>
157
		    	 
158
 
159
		    </fieldset>
160
		    {% endwith %}
161
		    {% endwith %}
162
		    {% endfor %}
163
	    </div>
164
	    
165
    	{% endfor %}
166
	</div>
167
    {% endwith %}
168
    {% endwith %}
169
	 
170
    <div class="form-row submit">
171
   		<input type="submit" value="CONTINUE" class="submit altcol" autocomplete="off">
172
	</div>     
173
</form>
174
	 
175
<script>
176
	
177
</script>	 
178
 
179
{% endblock %}
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form_demo_bak.html
1
{% extends "im/account_base.html" %}
2

  
3
{% load filters %}
4
{% block headjs %}
5
	{{ block.super }}	 
6
	<script src="{{ IM_STATIC_URL }}js/quotas.js"></script>	
7
{% endblock %}	
8
{% block page.body %}
9
 
10
	
11
<form action="" method="post" class="withlabels quotas-form">{% csrf_token %}
12
	 
13
    <fieldset class="with-info">
14
    	<legend>
15
    		1. CREATE GROUP
16
			<span class="info"> 
17
		    	<em>more info</em>
18
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
19
	    	</span>    		
20
    	</legend>
21
        
22
        {% include "im/form_render.html" %}
23
		
24
<!-- 
25
		<div class="double-checks">
26
    		<label>Max users per group</label>
27
    		<div class="form-row">
28
    			<p class="clearfix">
29
    				<label for="members_unlimited">Unlimited</label>
30
    				<input type="checkbox" id="members_unlimited" name="members_unlimited" class="unlimited" checked="checked">
31
    				<span class="info"> 
32
				    	<em>more info</em>
33
				    	<span>Help Text Help Text Help Text Text Help Text Help Text</span>
34
			    	</span>  
35
    			</p>
36
    		</div>
37
    		<div class="form-row">
38
    			<p class="clearfix">
39
    				<label for="members_limited">Limited</label>
40
    				<input type="checkbox" id="members_limited" name="members_limited" class="limited">
41
       				<input type="text" id="members_uplimit" name="members_uplimit" />
42
	       			  		 
43
    			</p>
44
    			
45
    		</div>
46
    		
47
    	</div> 
48
 -->
49
    </fieldset>     
50
    
51
    <fieldset id="icons">
52
    	<legend>
53
    		2. CHOOSE RESOURCES
54
    		<span class="info"> 
55
		    	<em>more info</em>
56
		    	<span>Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text Help Text</span>
57
	    	</span>    
58
    	</legend>
59

  
60
    {% with resource_catalog|lookup:'resources' as resources %}
61
    {% with resource_catalog|lookup:'groups' as groups %}    	
62
    	<ul class="clearfix">
63
            {% for g, rs in groups.items %}   
64
            {% with resource_presentation|lookup:g as group_info %} 		
65
    		<li>
66
    			<a href="#{{ g }}" id="{{'group_'|add:g}}"><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
67
    			<input type="hidden" name="{{ 'is_selected_'|add:g }}"  id="{{ 'id_is_selected_'|add:g }}" value="0">
68
    			<p class="msg">{{ group_info.help_text }}</p>
69
    		</li>
70
    		{% endwith %}
71
            {% endfor %}
72
    	</ul>
73
    	
74
    </fieldset>
75
   
76
    <div class="foo">
77
    
78
    </div>
79
    <div class="not-foo">
80
        {% for g, rs in groups.items %}
81
        
82
        <div class="group {{'group_'|add:g}}" id="{{ g }}">
83
			<a href="#icons" class="delete">X remove resource</a>	
84
		    {% for r in rs %}
85
		    {% with resource_presentation|lookup:r as resource_info %}
86
		    {% with resources|lookup:r as resource%}
87
		    <fieldset class="quota">
88
		    	<legend>
89
		    		{% if resource_info.is_abbreviation %}
90
		    			{{ r|get_value_after_dot|upper }}
91
		    		{% else %}
92
		    			{{ r|get_value_after_dot|capfirst }}
93
		    		{% endif %}
94
		    		<span class="info"> 
95
				    	<em>more info</em>
96
				    	<span>{{ resource_info.help_text }}</span>
97
			    	</span>  
98
		    	</legend>
99
<!--	    	<div class="form-row">
100
		    		<p class="clearfix">
101
		    			<label for="num_storage">Total storage</label>
102
		    			<input type="text" name="num_storage">
103
		    			<span class="extra-img">&nbsp;</span>
104
		         		<span class="info"><em>more info</em><span>Help Text</span></span>
105
		    		</p>
106
		    	</div>-->
107
 				<!--
108
 				<div class="double-checks">
109
		    		<label>
110
		    			Max {% if resource_info.is_abbreviation %}{{ r|get_value_after_dot|upper }}{% else %}{{ r|get_value_after_dot }}{% endif %}{% if not resource.unit %}s {% endif  %} per user
111
						{% if resource.unit %} 
112
						 	({{ resource.unit }})
113
						{% endif  %}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff