Revision ffb1e7a8

b/snf-astakos-app/astakos/im/api/__init__.py
172 172
                l.append(dict(url=absolute(reverse('invite')), name="Invitations"))
173 173
            l.append(dict(url=absolute(reverse('feedback')), name="Feedback"))
174 174
            l.append(dict(url=absolute(reverse('group_list')), name="Groups"))
175
            l.append(dict(url=absolute(reverse('resource_list')), name="Resources"))
175 176
        if with_signout:
176 177
            l.append(dict(url=absolute(reverse('logout')), name="Sign out"))
177 178

  
b/snf-astakos-app/astakos/im/management/commands/group_add.py
39 39
from os.path import abspath
40 40

  
41 41
from django.core.management.base import BaseCommand, CommandError
42
from django.contrib.auth.models import Group
42

  
43
from astakos.im.models import AstakosGroup
43 44

  
44 45
from ._common import add_group_permission
45 46

  
......
54 55
        name = args[0].decode('utf8')
55 56
        
56 57
        try:
57
            Group.objects.get(name=name)
58
            AstakosGroup.objects.get(name=name)
58 59
            raise CommandError("A group with this name already exists")
59
        except Group.DoesNotExist, e:
60
            group = Group(name=name)
60
        except AstakosGroup.DoesNotExist, e:
61
            group = AstakosGroup(name=name)
61 62
            group.save()
62 63
            msg = "Created group id %d" % (group.id,)
63 64
            self.stdout.write(msg + '\n')
/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 add_group_permission
43

  
44
class Command(BaseCommand):
45
    args = "<groupname> <permission> [<permissions> ...]"
46
    help = "Add group permissions"
47
    
48
    def handle(self, *args, **options):
49
        if len(args) < 2:
50
            raise CommandError("Please provide a group name and at least one permission")
51
        
52
        group = None
53
        try:
54
            if args[0].isdigit():
55
                group = Group.objects.get(id=args[0])
56
            else:
57
                group = Group.objects.get(name=args[0])
58
        except Group.DoesNotExist, e:
59
            raise CommandError("Invalid group")
60
        
61
        try:
62
            content_type = ContentType.objects.get(app_label='im',
63
                                                       model='astakosuser')
64
            for pname in args[1:]:
65
                r, created = add_group_permission(group, pname)
66
                if created:
67
                    self.stdout.write('Permission: %s created successfully\n' % pname)
68
                if r == 0:
69
                    self.stdout.write('Group has already permission: %s\n' % pname)
70
                else:
71
                    self.stdout.write('Permission: %s added successfully\n' % pname)
72
        except Exception, e:
73
            raise CommandError(e)
b/snf-astakos-app/astakos/im/management/commands/group_list.py
34 34
from optparse import make_option
35 35

  
36 36
from django.core.management.base import BaseCommand, CommandError
37
from django.contrib.auth.models import Group
38 37

  
39
from astakos.im.models import AstakosUser
38
from astakos.im.models import AstakosUser, AstakosGroup
40 39

  
41 40
from ._common import format_bool
42 41

  
43 42

  
44 43
class Command(BaseCommand):
45
    help = "List g"
44
    help = "List groups"
46 45
    
47 46
    option_list = BaseCommand.option_list + (
48 47
        make_option('-c',
......
50 49
            dest='csv',
51 50
            default=False,
52 51
            help="Use pipes to separate values"),
52
        make_option('-p',
53
            action='store_true',
54
            dest='pending',
55
            default=False,
56
            help="List only groups pending enable"),
53 57
    )
54 58
    
55 59
    def handle(self, *args, **options):
56 60
        if args:
57 61
            raise CommandError("Command doesn't accept any arguments")
58 62
        
59
        groups = Group.objects.all()
63
        groups = AstakosGroup.objects.all()
64
        
65
        if options.get('pending'):
66
            groups = filter(lambda g: g.is_disabled, groups)
60 67
        
61
        labels = ('id', 'name', 'permissions')
62
        columns = (3, 12, 50)
68
        labels = ('id', 'name', 'enabled', 'permissions')
69
        columns = (3, 12, 12, 50)
63 70
        
64
        if not options['csv']:
71
        if not options.get('csv'):
65 72
            line = ' '.join(l.rjust(w) for l, w in zip(labels, columns))
66 73
            self.stdout.write(line + '\n')
67 74
            sep = '-' * len(line)
68 75
            self.stdout.write(sep + '\n')
69 76
        
70 77
        for group in groups:
71
            fields = (str(group.id), group.name,
72
                      ','.join(p.codename for p in group.permissions.all()))
78
            fields = (  str(group.id),
79
                        group.name,
80
                        format_bool(group.is_enabled),
81
                        ','.join(p.codename for p in group.permissions.all()))
73 82
            
74
            if options['csv']:
83
            if options.get('csv'):
75 84
                line = '|'.join(fields)
76 85
            else:
77 86
                line = ' '.join(f.rjust(w) for f, w in zip(fields, columns))
/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
38
from django.core.exceptions import ValidationError
39

  
40
from astakos.im.models import AstakosUser
41
from ._common import remove_group_permission
42

  
43
class Command(BaseCommand):
44
    args = "<groupname> <permission> [<permissions> ...]"
45
    help = "Remove group permissions"
46
    
47
    def handle(self, *args, **options):
48
        if len(args) < 2:
49
            raise CommandError("Please provide a group name and at least one permission")
50
        
51
        group = None
52
        try:
53
            if args[0].isdigit():
54
                group = Group.objects.get(id=args[0])
55
            else:
56
                group = Group.objects.get(name=args[0])
57
        except Group.DoesNotExist, e:
58
            raise CommandError("Invalid group")
59
        
60
        try:
61
            for pname in args[1:]:
62
                r = remove_group_permission(group, pname)
63
                if r < 0:
64
                    self.stdout.write('Invalid permission codename: %s\n' % pname)
65
                elif r == 0:
66
                    self.stdout.write('Group has not permission: %s\n' % pname)
67
                elif r > 0:
68
                    self.stdout.write('Permission: %s removed successfully\n' % pname)
69
        except Exception, e:
70
            raise CommandError(e)
b/snf-astakos-app/astakos/im/management/commands/group_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 Permission
38
from django.contrib.contenttypes.models import ContentType
39
from django.core.exceptions import ValidationError
40

  
41
from astakos.im.models import AstakosUser, AstakosGroup
42
from ._common import add_group_permission
43

  
44
class Command(BaseCommand):
45
    args = "<groupname>"
46
    help = "Update group"
47
    
48
    option_list = BaseCommand.option_list + (
49
        make_option('--add-permission',
50
            dest='add-permission',
51
            help="Add user permission"),
52
        make_option('--delete-permission',
53
            dest='delete-permission',
54
            help="Delete user permission"),
55
        make_option('--enable',
56
            action='store_true',
57
            dest='enable',
58
            default=False,
59
            help="Enable group"),
60
    )
61
    
62
    def handle(self, *args, **options):
63
        if len(args) < 1:
64
            raise CommandError("Please provide a group identifier")
65
        
66
        group = None
67
        try:
68
            if args[0].isdigit():
69
                group = AstakosGroup.objects.get(id=args[0])
70
            else:
71
                group = AstakosGroup.objects.get(name=args[0])
72
        except AstakosGroup.DoesNotExist, e:
73
            raise CommandError("Invalid group")
74
        
75
        try:
76
            content_type = ContentType.objects.get(app_label='im',
77
                                                       model='astakosuser')
78
            
79
            pname = options.get('add-permission')
80
            if pname:
81
                r, created = add_group_permission(group, pname)
82
                if created:
83
                    self.stdout.write('Permission: %s created successfully\n' % pname)
84
                if r == 0:
85
                    self.stdout.write('Group has already permission: %s\n' % pname)
86
                else:
87
                    self.stdout.write('Permission: %s added successfully\n' % pname)
88
            
89
            pname = options.get('delete-permission')
90
            if pname:
91
                r = remove_group_permission(group, pname)
92
                if r < 0:
93
                    self.stdout.write('Invalid permission codename: %s\n' % pname)
94
                elif r == 0:
95
                    self.stdout.write('Group has not permission: %s\n' % pname)
96
                elif r > 0:
97
                    self.stdout.write('Permission: %s removed successfully\n' % pname)
98
            
99
            if options.get('enable'):
100
                group.enable()
101
        except Exception, e:
102
            raise CommandError(e)
b/snf-astakos-app/astakos/im/models.py
41 41
from base64 import b64encode
42 42
from urlparse import urlparse, urlunparse
43 43
from random import randint
44
from collections import defaultdict
44 45

  
45 46
from django.db import models, IntegrityError
46 47
from django.contrib.auth.models import User, UserManager, Group
......
120 121
    
121 122
    @property
122 123
    def is_disabled(self):
123
        if not approval_date:
124
            return False
125
        return True
124
        if not self.approval_date:
125
            return True
126
        return False
126 127
    
127 128
    @property
128
    def is_active(self):
129
    def is_enabled(self):
129 130
        if self.is_disabled:
130 131
            return False
131 132
        if not self.issue_date:
......
143 144
    def participants(self):
144 145
        return len(self.approved_members)
145 146
    
146
    def approve(self):
147
    def enable(self):
147 148
        self.approval_date = datetime.now()
148 149
        self.save()
149 150
    
150
    def disapprove(self):
151
    def disable(self):
151 152
        self.approval_date = None
152 153
        self.save()
153 154
    
......
172 173
        return map(lambda m:m.person, f)
173 174
    
174 175
    @property
175
    def policies(self):
176
        return self.astakosgroupquota_set.all()
176
    def quota(self):
177
        d = {}
178
        for q in  self.astakosgroupquota_set.all():
179
            d[q.resource.name] = q.limit
180
        return d
177 181
    
178 182
    @property
179 183
    def has_undefined_policies(self):
......
255 259
            return Invitation.objects.get(username=self.email)
256 260
        except Invitation.DoesNotExist:
257 261
            return None
258

  
262
    
263
    @property
264
    def quota(self):
265
        d = defaultdict(int)
266
        for q in  self.astakosuserquota_set.all():
267
            d[q.resource.name] += q.limit
268
        for g in self.astakos_groups.all():
269
            if not g.is_enabled:
270
                continue
271
            for r, limit in g.quota.iteritems():
272
                d[r] += limit
273
        # TODO set default for remaining
274
        return d
275
        
259 276
    def save(self, update_timestamps=True, **kwargs):
260 277
        if update_timestamps:
261 278
            if not self.id:
......
340 357
            self.save()
341 358
            return False
342 359
        return True
343
    
344
    def enroll_group(self, group):
345
        self.membership_set.add(group)
346
    
347
    def get_astakos_groups(self, approved=True):
348
        if approved:
349
            return self.membership_set().filter(is_approved=True)
350
        return self.membership_set().all()
351 360

  
352 361
class Membership(models.Model):
353 362
    person = models.ForeignKey(AstakosUser)
......
358 367
    class Meta:
359 368
        unique_together = ("person", "group")
360 369
    
361
    def save(self):
370
    def save(self, *args, **kwargs):
362 371
        if not self.id:
363 372
            if not self.group.moderation_enabled:
364 373
                self.date_joined = datetime.now()
365
        super(Membership, self).save()
374
        super(Membership, self).save(*args, **kwargs)
366 375
    
367 376
    @property
368 377
    def is_approved(self):
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
1 1
{% extends "im/account_base.html" %}
2 2

  
3
{% load filters %}
4

  
3 5
{% block page.body %}
4 6
<div class="maincol {% block innerpage.class %}{% endblock %}">
5 7
        <table class="zebra-striped id-sorted">
......
10 12
                <th>Type: {{object.kind}}</th>
11 13
              </tr>
12 14
              <tr>
13
                <th>Issue date: {{object.issue_date}}</th>
15
                <th>Issue date: {{object.issue_date|date:"d/m/Y"}}</th>
14 16
              </tr>
15 17
              <tr>
16
                <th>Expiration date: {{object.expiration_date}}</th>
18
                <th>Expiration date: {{object.expiration_date|date:"d/m/Y"}}</th>
17 19
              </tr>
18 20
              <tr>
19 21
                <th>Moderation: {% if object.moderation_enabled%}Yes{% else %}No{% endif %}</th>
......
21 23
              <tr>
22 24
                <th>Owner: {% for o in object.owner.all %}
23 25
                                {% if user == o %}
24
                                    Me!
26
                                    Me
25 27
                                {% else%}
26 28
                                    {{o.realname}} ({{o.email}})
27 29
                                
......
29 31
                            {% endfor %}
30 32
                </th>
31 33
              </tr>
34
              <tr>
35
                <th>Enabled: {% if object.is_enabled %}Yes{% else %}No{% endif %}</th>
36
              </tr>
32 37
        </table>
33 38
    <div class="section">
34 39
        <h2>Members:</h2>
......
54 59
                    {% else %}
55 60
                    <td>Pending</td>
56 61
                        {% if user in m.group.owner.all %}
57
                            <td><a href="{% url approve_member m.id %}">Approve</a></td>
58
                            <td><a href="{% url disapprove_member m.id %}">Disapprove</a></td>
62
                            <td><a href="{% url approve_member m.group.id m.person.id %}">Approve</a></td>
63
                            <td><a href="{% url disapprove_member m.group.id m.person.id  %}">Disapprove</a></td>
59 64
                        {% endif %}
60 65
                    {% endif %}
61 66
                {% endif %}
......
78 83
              </tr>
79 84
            </thead>
80 85
            <tbody>
81
            {% for q in quota %}
86
            {% for k in quota|dkeys %}
82 87
                <tr>
83
                    <td>{{q.resource.name}}</td>
84
                    <td>{{q.limit}}</td>
88
                    <td>{{ k }}</td>
89
                    <td>{{ quota|lookup:k }}</td>
85 90
                  </tr>
86 91
            {% endfor %}
87 92
            </tbody>
......
90 95
            <p>No policies</p>
91 96
        {% endif %}
92 97
    </div>
93
    {% if more_policies %}
98
    {% if user in object.owner.all and more_policies %}
94 99
    <div class="rightcol">
95 100
        <form action="{% url group_policies_add object.id %}" method="post" class="innerlabels signup">{% csrf_token %}
96 101
            <h2><span>NEW POLICY</span></h2>
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html
29 29
                <th>Expiration date</th>
30 30
                <th>Owner?</th>
31 31
                <th>Participants</th>
32
                <th>Enabled?</th>
32 33
                <th>Moderation?</th>
33 34
                <th>Enrollment status</th>
34 35
              </tr>
......
38 39
              <tr>
39 40
                <td><a class="extra-link" href="{% url group_detail o.id %}">{{o.name}}</a></td>
40 41
                <td>{{o.kind}}</td>
41
                <td>{{o.issue_date|date:"D d M Y"}}</td>
42
                <td>{{o.expiration_date|date:"D d M Y"}}</td>
42
                <td>{{o.issue_date|date:"d/m/Y"}}</td>
43
                <td>{{o.expiration_date|date:"d/m/Y"}}</td>
43 44
                <td>{% if user in o.owner.all %}Yes{% else %}No{% endif %}</td>
44 45
                <td>{{ o.approved_members|length }}/{{ o.members|length }}</td>
46
                <td>{% if o.is_enabled %}Yes{% else %}No{% endif %}</td>
45 47
                <td>{% if o.moderation_enabled%}Yes{% else %}No{% endif %}</td>
46 48
                {% if user in o.approved_members %}
47 49
                    <td>Active</td>
b/snf-astakos-app/astakos/im/templates/im/astakosuserquota_list.html
1
{% extends "im/account_base.html" %}
2

  
3
{% load filters %}
4

  
5
{% block page.body %}
6
<div class="maincol {% block innerpage.class %}{% endblock %}">
7
    <div class="section">
8
        {% if quota %}
9
          <table class="zebra-striped id-sorted">
10
            <thead>
11
              <tr>
12
                <th>Resource</th>
13
                <th>Limit</th>
14
              </tr>
15
            </thead>
16
            <tbody>
17
            {% for k in quota|dkeys %}
18
                <tr>
19
                    <td>{{ k }}</td>
20
                    <td>{{ quota|lookup:k }}</td>
21
                  </tr>
22
            {% endfor %}
23
            </tbody>
24
        </table>
25
        {% else %}
26
            <p>No policies</p>
27
        {% endif %}
28
    </div>
29
</div>
30
{% endblock %}
b/snf-astakos-app/astakos/im/urls.py
49 49
    url(r'^approval_terms/?$', 'approval_terms', {}, name='latest_terms'),
50 50
    url(r'^approval_terms/(?P<term_id>\d+)/?$', 'approval_terms'),
51 51
    url(r'^password/?$', 'change_password', {}, name='password_change'),
52
    url(r'^resources/?$', 'resource_list', {}, name='resource_list'),
52 53
    url(r'^group/add/?$', 'group_add', {}, name='group_add'),
53 54
    url(r'^group/list/?$', 'group_list', {}, name='group_list'),
54 55
    url(r'^group/(?P<group_id>\d+)/?$', 'group_detail', {}, name='group_detail'),
55
    url(r'^group/(?P<group_id>\d+)/policies/list/?$', 'group_policies_list', {}, name='group_policies_list'),
56
    #url(r'^group/(?P<group_id>\d+)/policies/list/?$', 'group_policies_list', {}, name='group_policies_list'),
56 57
    url(r'^group/(?P<group_id>\d+)/policies/add/?$', 'group_policies_add', {}, name='group_policies_add'),
57 58
    url(r'^group/search/?$', 'group_search', {}, name='group_search'),
58 59
    url(r'^group/(?P<group_id>\d+)/join/?$', 'group_join', {}, name='group_join'),
59 60
    url(r'^group/(?P<group_id>\d+)/leave/?$', 'group_leave', {}, name='group_leave'),
60
    url(r'^group/(?P<group_id>\d+)/request/approval/?$', 'group_approval_request', {}, name='group_approval_request'),
61
    url(r'^group/(?P<membership_id>\d+)/approve/?$', 'approve_member', {}, name='approve_member'),
62
    url(r'^group/(?P<membership_id>\d+)/disapprove/?$', 'disapprove_member', {}, name='disapprove_member'),
61
    #url(r'^group/(?P<group_id>\d+)/request/approval/?$', 'group_approval_request', {}, name='group_approval_request'),
62
    url(r'^group/(?P<group_id>\d+)/(?P<user_id>\d+)/approve/?$', 'approve_member', {}, name='approve_member'),
63
    url(r'^group/(?P<group_id>\d+)/(?P<user_id>\d+)/disapprove/?$', 'disapprove_member', {}, name='disapprove_member'),
63 64
)
64 65

  
65 66
if EMAILCHANGE_ENABLED:
b/snf-astakos-app/astakos/im/views.py
610 610
                         AstakosGroup.objects.all(),
611 611
                         object_id=group_id,
612 612
                         extra_context = {'form':get_astakos_group_policy_creation_form(group),
613
                                          'quota':group.policies,
613
                                          'quota':group.quota,
614 614
                                          'more_policies':group.has_undefined_policies})
615 615

  
616 616
@signed_terms_required
......
631 631
                         template_name = 'im/astakosgroup_detail.html',
632 632
                         post_save_redirect = reverse('group_detail', kwargs=dict(group_id=group_id)),
633 633
                         extra_context = {'group':group,
634
                                          'quota':group.policies,
634
                                          'quota':group.quota,
635 635
                                          'more_policies':group.has_undefined_policies})
636 636
@signed_terms_required
637 637
@login_required
......
686 686
def handle_membership():
687 687
    def decorator(func):
688 688
        @wraps(func)
689
        def wrapper(request, membership_id):
689
        def wrapper(request, group_id, user_id):
690 690
            try:
691
                m = Membership.objects.select_related().get(id=membership_id)
691
                m = Membership.objects.select_related().get(group__id=group_id, person__id=user_id)
692 692
            except Membership.DoesNotExist:
693 693
                return HttpResponseBadRequest(_('Invalid membership.'))
694 694
            else:
......
698 698
                return render_response(template='im/astakosgroup_detail.html',
699 699
                                       context_instance=get_context(request),
700 700
                                       object=m.group,
701
                                       quota=m.group.policies,
701
                                       quota=m.group.quota,
702 702
                                       more_policies=m.group.has_undefined_policies)
703 703
        return wrapper
704 704
    return decorator
......
730 730
        logger.exception(e)
731 731
        msg = _('Something went wrong during %s\'s disapproval.' % realname)
732 732
        messages.error(request, msg)
733

  
734
@signed_terms_required
735
@login_required
736
def resource_list(request):
737
    return render_response(template='im/astakosuserquota_list.html',
738
                           context_instance=get_context(request),
739
                           quota=request.user.quota)

Also available in: Unified diff