Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / user-modify.py @ 9e812adf

History | View | Annotate | Download (10.1 kB)

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 astakos.im.functions import (activate, deactivate)
42
from astakos.im import quotas
43
from ._common import remove_user_permission, add_user_permission, is_uuid
44
from snf_django.lib.db.transaction import commit_on_success_strict
45
import string
46

    
47

    
48
class Command(BaseCommand):
49
    args = "<user ID>"
50
    help = "Modify a user's attributes"
51

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

    
116
    )
117

    
118
    @commit_on_success_strict()
119
    def handle(self, *args, **options):
120
        if len(args) != 1:
121
            raise CommandError("Please provide a user ID")
122

    
123
        if args[0].isdigit():
124
            try:
125
                user = AstakosUser.objects.get(id=int(args[0]))
126
            except AstakosUser.DoesNotExist:
127
                raise CommandError("Invalid user ID")
128
        elif is_uuid(args[0]):
129
            try:
130
                user = AstakosUser.objects.get(uuid=args[0])
131
            except AstakosUser.DoesNotExist:
132
                raise CommandError("Invalid user UUID")
133
        else:
134
            raise CommandError(("Invalid user identification: "
135
                                "you should provide a valid user ID "
136
                                "or a valid user UUID"))
137

    
138
        if options.get('admin'):
139
            user.is_superuser = True
140
        elif options.get('noadmin'):
141
            user.is_superuser = False
142

    
143
        if options.get('active'):
144
            activate(user)
145
        elif options.get('inactive'):
146
            deactivate(user)
147

    
148
        invitations = options.get('invitations')
149
        if invitations is not None:
150
            user.invitations = int(invitations)
151

    
152
        groupname = options.get('add-group')
153
        if groupname is not None:
154
            try:
155
                group = Group.objects.get(name=groupname)
156
                user.groups.add(group)
157
            except Group.DoesNotExist, e:
158
                self.stdout.write(
159
                    "Group named %s does not exist\n" % groupname)
160

    
161
        groupname = options.get('delete-group')
162
        if groupname is not None:
163
            try:
164
                group = Group.objects.get(name=groupname)
165
                user.groups.remove(group)
166
            except Group.DoesNotExist, e:
167
                self.stdout.write(
168
                    "Group named %s does not exist\n" % groupname)
169

    
170
        pname = options.get('add-permission')
171
        if pname is not None:
172
            try:
173
                r, created = add_user_permission(user, pname)
174
                if created:
175
                    self.stdout.write(
176
                        'Permission: %s created successfully\n' % pname)
177
                if r > 0:
178
                    self.stdout.write(
179
                        'Permission: %s added successfully\n' % pname)
180
                elif r == 0:
181
                    self.stdout.write(
182
                        'User has already permission: %s\n' % pname)
183
            except Exception, e:
184
                raise CommandError(e)
185

    
186
        pname = options.get('delete-permission')
187
        if pname is not None and not user.has_perm(pname):
188
            try:
189
                r = remove_user_permission(user, pname)
190
                if r < 0:
191
                    self.stdout.write(
192
                        'Invalid permission codename: %s\n' % pname)
193
                elif r == 0:
194
                    self.stdout.write('User has not permission: %s\n' % pname)
195
                elif r > 0:
196
                    self.stdout.write(
197
                        'Permission: %s removed successfully\n' % pname)
198
            except Exception, e:
199
                raise CommandError(e)
200

    
201
        level = options.get('level')
202
        if level is not None:
203
            user.level = int(level)
204

    
205
        password = options.get('password')
206
        if password is not None:
207
            user.set_password(password)
208

    
209
        password = None
210
        if options['renew_password']:
211
            password = AstakosUser.objects.make_random_password()
212
            user.set_password(password)
213

    
214
        if options['renew_token']:
215
            user.renew_token()
216

    
217
        try:
218
            user.save()
219
        except ValidationError, e:
220
            raise CommandError(e)
221

    
222
        if password:
223
            self.stdout.write('User\'s new password: %s\n' % password)
224

    
225
        set_base_quota = options.get('set_base_quota')
226
        if set_base_quota is not None:
227
            resource, capacity = set_base_quota
228
            self.set_limit(user, resource, capacity, False)
229

    
230
    def set_limit(self, user, resource, capacity, force):
231
        if capacity != 'default':
232
            try:
233
                capacity = int(capacity)
234
            except ValueError:
235
                m = "Please specify capacity as a decimal integer or 'default'"
236
                raise CommandError(m)
237

    
238
        try:
239
            quota, default_capacity = user.get_resource_policy(resource)
240
        except Resource.DoesNotExist:
241
            raise CommandError("No such resource: %s" % resource)
242

    
243
        current = quota.capacity if quota is not None else 'default'
244

    
245
        if not force:
246
            self.stdout.write("user: %s (%s)\n" % (user.uuid, user.username))
247
            self.stdout.write("default capacity: %s\n" % default_capacity)
248
            self.stdout.write("current capacity: %s\n" % current)
249
            self.stdout.write("new capacity: %s\n" % capacity)
250
            self.stdout.write("Confirm? (y/n) ")
251
            response = raw_input()
252
            if string.lower(response) not in ['y', 'yes']:
253
                self.stdout.write("Aborted.\n")
254
                return
255

    
256
        if capacity == 'default':
257
            try:
258
                quotas.remove_base_quota(user, resource)
259
            except Exception as e:
260
                import traceback
261
                traceback.print_exc()
262
                raise CommandError("Failed to remove policy: %s" % e)
263
        else:
264
            try:
265
                quotas.add_base_quota(user, resource, capacity)
266
            except Exception as e:
267
                raise CommandError("Failed to add policy: %s" % e)