Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / user-modify.py @ 398a9604

History | View | Annotate | Download (12.5 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
import string
35

    
36
from optparse import make_option
37

    
38
from django.core.management.base import BaseCommand, CommandError
39
from django.contrib.auth.models import Group
40
from django.core.exceptions import ValidationError
41

    
42
from astakos.im.models import AstakosUser
43
from astakos.im import quotas
44
from astakos.im import activation_backends
45
from ._common import remove_user_permission, add_user_permission, is_uuid
46
from snf_django.lib.db.transaction import commit_on_success_strict
47

    
48
activation_backend = activation_backends.get_backend()
49

    
50

    
51
class Command(BaseCommand):
52
    args = "<user ID>"
53
    help = "Modify a user's attributes"
54

    
55
    option_list = BaseCommand.option_list + (
56
        make_option('--invitations',
57
                    dest='invitations',
58
                    metavar='NUM',
59
                    help="Update user's invitations"),
60
        make_option('--level',
61
                    dest='level',
62
                    metavar='NUM',
63
                    help="Update user's level"),
64
        make_option('--password',
65
                    dest='password',
66
                    metavar='PASSWORD',
67
                    help="Set user's password"),
68
        make_option('--renew-token',
69
                    action='store_true',
70
                    dest='renew_token',
71
                    default=False,
72
                    help="Renew the user's token"),
73
        make_option('--renew-password',
74
                    action='store_true',
75
                    dest='renew_password',
76
                    default=False,
77
                    help="Renew the user's password"),
78
        make_option('--set-admin',
79
                    action='store_true',
80
                    dest='admin',
81
                    default=False,
82
                    help="Give user admin rights"),
83
        make_option('--set-noadmin',
84
                    action='store_true',
85
                    dest='noadmin',
86
                    default=False,
87
                    help="Revoke user's admin rights"),
88
        make_option('--set-active',
89
                    action='store_true',
90
                    dest='active',
91
                    default=False,
92
                    help="Change user's state to active"),
93
        make_option('--set-inactive',
94
                    action='store_true',
95
                    dest='inactive',
96
                    default=False,
97
                    help="Change user's state to inactive"),
98
        make_option('--inactive-reason',
99
                    dest='inactive_reason',
100
                    help="Reason user got inactive"),
101
        make_option('--add-group',
102
                    dest='add-group',
103
                    help="Add user group"),
104
        make_option('--delete-group',
105
                    dest='delete-group',
106
                    help="Delete user group"),
107
        make_option('--add-permission',
108
                    dest='add-permission',
109
                    help="Add user permission"),
110
        make_option('--delete-permission',
111
                    dest='delete-permission',
112
                    help="Delete user permission"),
113
        make_option('--accept',
114
                    dest='accept',
115
                    action='store_true',
116
                    help="Accept user"),
117
        make_option('--verify',
118
                    dest='verify',
119
                    action='store_true',
120
                    help="Verify user email"),
121
        make_option('--reject',
122
                    dest='reject',
123
                    action='store_true',
124
                    help="Reject user"),
125
        make_option('--reject-reason',
126
                    dest='reject_reason',
127
                    help="Reason user got rejected"),
128
        make_option('--set-base-quota',
129
                    dest='set_base_quota',
130
                    metavar='<resource> <capacity>',
131
                    nargs=2,
132
                    help=("Set base quota for a specified resource. "
133
                          "The special value 'default' sets the user base "
134
                          "quota to the default value.")
135
                    ),
136

    
137
    )
138

    
139
    @commit_on_success_strict()
140
    def handle(self, *args, **options):
141
        if len(args) != 1:
142
            raise CommandError("Please provide a user ID")
143

    
144
        if args[0].isdigit():
145
            try:
146
                user = AstakosUser.objects.get(id=int(args[0]))
147
            except AstakosUser.DoesNotExist:
148
                raise CommandError("Invalid user ID")
149
        elif is_uuid(args[0]):
150
            try:
151
                user = AstakosUser.objects.get(uuid=args[0])
152
            except AstakosUser.DoesNotExist:
153
                raise CommandError("Invalid user UUID")
154
        else:
155
            raise CommandError(("Invalid user identification: "
156
                                "you should provide a valid user ID "
157
                                "or a valid user UUID"))
158

    
159
        if options.get('admin'):
160
            user.is_superuser = True
161
        elif options.get('noadmin'):
162
            user.is_superuser = False
163

    
164
        if options.get('reject'):
165
            reject_reason = options.get('reject_reason', None)
166
            res = activation_backend.handle_moderation(
167
                user,
168
                accept=False,
169
                reject_reason=reject_reason)
170
            activation_backend.send_result_notifications(res, user)
171
            if res.is_error():
172
                print "Failed to reject.", res.message
173
            else:
174
                print "Account rejected"
175

    
176
        if options.get('verify'):
177
            res = activation_backend.handle_verification(
178
                user,
179
                user.verification_code)
180
            #activation_backend.send_result_notifications(res, user)
181
            if res.is_error():
182
                print "Failed to verify.", res.message
183
            else:
184
                print "Account verified (%s)" % res.status_display()
185

    
186
        if options.get('accept'):
187
            res = activation_backend.handle_moderation(user, accept=True)
188
            activation_backend.send_result_notifications(res, user)
189
            if res.is_error():
190
                print "Failed to accept.", res.message
191
            else:
192
                print "Account accepted and activated"
193

    
194
        if options.get('active'):
195
            res = activation_backend.activate_user(user)
196
            if res.is_error():
197
                print "Failed to activate.", res.message
198
            else:
199
                print "Account %s activated" % user.username
200

    
201
        elif options.get('inactive'):
202
            res = activation_backend.deactivate_user(
203
                user,
204
                reason=options.get('inactive_reason', None))
205
            if res.is_error():
206
                print "Failed to deactivate,", res.message
207
            else:
208
                print "Account %s deactivated" % user.username
209

    
210
        invitations = options.get('invitations')
211
        if invitations is not None:
212
            user.invitations = int(invitations)
213

    
214
        groupname = options.get('add-group')
215
        if groupname is not None:
216
            try:
217
                group = Group.objects.get(name=groupname)
218
                user.groups.add(group)
219
            except Group.DoesNotExist, e:
220
                self.stdout.write(
221
                    "Group named %s does not exist\n" % groupname)
222

    
223
        groupname = options.get('delete-group')
224
        if groupname is not None:
225
            try:
226
                group = Group.objects.get(name=groupname)
227
                user.groups.remove(group)
228
            except Group.DoesNotExist, e:
229
                self.stdout.write(
230
                    "Group named %s does not exist\n" % groupname)
231

    
232
        pname = options.get('add-permission')
233
        if pname is not None:
234
            try:
235
                r, created = add_user_permission(user, pname)
236
                if created:
237
                    self.stdout.write(
238
                        'Permission: %s created successfully\n' % pname)
239
                if r > 0:
240
                    self.stdout.write(
241
                        'Permission: %s added successfully\n' % pname)
242
                elif r == 0:
243
                    self.stdout.write(
244
                        'User has already permission: %s\n' % pname)
245
            except Exception, e:
246
                raise CommandError(e)
247

    
248
        pname = options.get('delete-permission')
249
        if pname is not None and not user.has_perm(pname):
250
            try:
251
                r = remove_user_permission(user, pname)
252
                if r < 0:
253
                    self.stdout.write(
254
                        'Invalid permission codename: %s\n' % pname)
255
                elif r == 0:
256
                    self.stdout.write('User has not permission: %s\n' % pname)
257
                elif r > 0:
258
                    self.stdout.write(
259
                        'Permission: %s removed successfully\n' % pname)
260
            except Exception, e:
261
                raise CommandError(e)
262

    
263
        level = options.get('level')
264
        if level is not None:
265
            user.level = int(level)
266

    
267
        password = options.get('password')
268
        if password is not None:
269
            user.set_password(password)
270

    
271
        password = None
272
        if options['renew_password']:
273
            password = AstakosUser.objects.make_random_password()
274
            user.set_password(password)
275

    
276
        if options['renew_token']:
277
            user.renew_token()
278

    
279
        try:
280
            user.save()
281
        except ValidationError, e:
282
            raise CommandError(e)
283

    
284
        if password:
285
            self.stdout.write('User\'s new password: %s\n' % password)
286

    
287
        set_base_quota = options.get('set_base_quota')
288
        if set_base_quota is not None:
289
            resource, capacity = set_base_quota
290
            self.set_limit(user, resource, capacity, False)
291

    
292
    def set_limit(self, user, resource, capacity, force):
293
        if capacity != 'default':
294
            try:
295
                capacity = int(capacity)
296
            except ValueError:
297
                m = "Please specify capacity as a decimal integer or 'default'"
298
                raise CommandError(m)
299

    
300
        try:
301
            quota, default_capacity = user.get_resource_policy(resource)
302
        except Resource.DoesNotExist:
303
            raise CommandError("No such resource: %s" % resource)
304

    
305
        current = quota.capacity if quota is not None else 'default'
306

    
307
        if not force:
308
            self.stdout.write("user: %s (%s)\n" % (user.uuid, user.username))
309
            self.stdout.write("default capacity: %s\n" % default_capacity)
310
            self.stdout.write("current capacity: %s\n" % current)
311
            self.stdout.write("new capacity: %s\n" % capacity)
312
            self.stdout.write("Confirm? (y/n) ")
313
            response = raw_input()
314
            if string.lower(response) not in ['y', 'yes']:
315
                self.stdout.write("Aborted.\n")
316
                return
317

    
318
        if capacity == 'default':
319
            try:
320
                quotas.remove_base_quota(user, resource)
321
            except Exception as e:
322
                import traceback
323
                traceback.print_exc()
324
                raise CommandError("Failed to remove policy: %s" % e)
325
        else:
326
            try:
327
                quotas.add_base_quota(user, resource, capacity)
328
            except Exception as e:
329
                raise CommandError("Failed to add policy: %s" % e)