Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / user-modify.py @ 64a43a9a

History | View | Annotate | Download (13.5 kB)

1
# Copyright 2012, 2013, 2014 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
from datetime import datetime
36

    
37
from optparse import make_option
38

    
39
from django.core import management
40
from django.db import transaction
41
from django.core.management.base import BaseCommand, CommandError
42
from django.contrib.auth.models import Group
43
from django.core.exceptions import ValidationError
44
from django.core.validators import validate_email
45

    
46
from astakos.im.models import AstakosUser
47
from astakos.im import activation_backends
48
from ._common import (remove_user_permission, add_user_permission, is_uuid)
49

    
50
activation_backend = activation_backends.get_backend()
51

    
52

    
53
class Command(BaseCommand):
54
    args = "<user ID> (or --all)"
55
    help = "Modify a user's attributes"
56

    
57
    option_list = BaseCommand.option_list + (
58
        make_option('--all',
59
                    action='store_true',
60
                    default=False,
61
                    help=("Operate on all users. Currently only setting "
62
                          "base quota is supported in this mode. Can be "
63
                          "combined with `--exclude'.")),
64
        make_option('--exclude',
65
                    help=("If `--all' is given, exclude users given as a "
66
                          "list of uuids: uuid1,uuid2,uuid3")),
67
        make_option('--invitations',
68
                    dest='invitations',
69
                    metavar='NUM',
70
                    help="Update user's invitations"),
71
        make_option('--level',
72
                    dest='level',
73
                    metavar='NUM',
74
                    help="Update user's level"),
75
        make_option('--password',
76
                    dest='password',
77
                    metavar='PASSWORD',
78
                    help="Set user's password"),
79
        make_option('--renew-token',
80
                    action='store_true',
81
                    dest='renew_token',
82
                    default=False,
83
                    help="Renew the user's token"),
84
        make_option('--renew-password',
85
                    action='store_true',
86
                    dest='renew_password',
87
                    default=False,
88
                    help="Renew the user's password"),
89
        make_option('--set-admin',
90
                    action='store_true',
91
                    dest='admin',
92
                    default=False,
93
                    help="Give user admin rights"),
94
        make_option('--set-noadmin',
95
                    action='store_true',
96
                    dest='noadmin',
97
                    default=False,
98
                    help="Revoke user's admin rights"),
99
        make_option('--set-active',
100
                    action='store_true',
101
                    dest='active',
102
                    default=False,
103
                    help="Change user's state to active"),
104
        make_option('--set-inactive',
105
                    action='store_true',
106
                    dest='inactive',
107
                    default=False,
108
                    help="Change user's state to inactive"),
109
        make_option('--inactive-reason',
110
                    dest='inactive_reason',
111
                    help="Reason user got inactive"),
112
        make_option('--add-group',
113
                    dest='add-group',
114
                    help="Add user group"),
115
        make_option('--delete-group',
116
                    dest='delete-group',
117
                    help="Delete user group"),
118
        make_option('--add-permission',
119
                    dest='add-permission',
120
                    help="Add user permission"),
121
        make_option('--delete-permission',
122
                    dest='delete-permission',
123
                    help="Delete user permission"),
124
        make_option('--accept',
125
                    dest='accept',
126
                    action='store_true',
127
                    help="Accept user"),
128
        make_option('--verify',
129
                    dest='verify',
130
                    action='store_true',
131
                    help="Verify user email"),
132
        make_option('--reject',
133
                    dest='reject',
134
                    action='store_true',
135
                    help="Reject user"),
136
        make_option('--reject-reason',
137
                    dest='reject_reason',
138
                    help="Reason user got rejected"),
139
        make_option('--sign-terms',
140
                    default=False,
141
                    action='store_true',
142
                    help="Sign terms"),
143
        make_option('-f', '--no-confirm',
144
                    action='store_true',
145
                    default=False,
146
                    dest='force',
147
                    help="Do not ask for confirmation"),
148
        make_option('--set-email',
149
                    dest='set-email',
150
                    help="Change user's email"),
151
        make_option('--delete',
152
                    dest='delete',
153
                    action='store_true',
154
                    help="Delete a non-accepted user"),
155
    )
156

    
157
    @transaction.commit_on_success
158
    def handle(self, *args, **options):
159
        if options['all']:
160
            if not args:
161
                return self.handle_all_users(*args, **options)
162
            else:
163
                raise CommandError("Please provide a user ID or --all")
164

    
165
        if len(args) != 1:
166
            raise CommandError("Please provide a user ID or --all")
167

    
168
        if options["exclude"] is not None:
169
            m = "Option --exclude is meaningful only combined with --all."
170
            raise CommandError(m)
171

    
172
        if args[0].isdigit():
173
            try:
174
                user = AstakosUser.objects.select_for_update().\
175
                    get(id=int(args[0]))
176
            except AstakosUser.DoesNotExist:
177
                raise CommandError("Invalid user ID")
178
        elif is_uuid(args[0]):
179
            try:
180
                user = AstakosUser.objects.get(uuid=args[0])
181
            except AstakosUser.DoesNotExist:
182
                raise CommandError("Invalid user UUID")
183
        else:
184
            raise CommandError(("Invalid user identification: "
185
                                "you should provide a valid user ID "
186
                                "or a valid user UUID"))
187

    
188
        if options.get('admin'):
189
            user.is_superuser = True
190
        elif options.get('noadmin'):
191
            user.is_superuser = False
192

    
193
        if options.get('reject'):
194
            reject_reason = options.get('reject_reason', None)
195
            res = activation_backend.handle_moderation(
196
                user,
197
                accept=False,
198
                reject_reason=reject_reason)
199
            activation_backend.send_result_notifications(res, user)
200
            if res.is_error():
201
                print "Failed to reject.", res.message
202
            else:
203
                print "Account rejected"
204

    
205
        if options.get('verify'):
206
            res = activation_backend.handle_verification(
207
                user,
208
                user.verification_code)
209
            #activation_backend.send_result_notifications(res, user)
210
            if res.is_error():
211
                print "Failed to verify.", res.message
212
            else:
213
                print "Account verified (%s)" % res.status_display()
214

    
215
        if options.get('accept'):
216
            res = activation_backend.handle_moderation(user, accept=True)
217
            activation_backend.send_result_notifications(res, user)
218
            if res.is_error():
219
                print "Failed to accept.", res.message
220
            else:
221
                print "Account accepted and activated"
222

    
223
        if options.get('active'):
224
            res = activation_backend.activate_user(user)
225
            if res.is_error():
226
                print "Failed to activate.", res.message
227
            else:
228
                print "Account %s activated" % user.username
229

    
230
        elif options.get('inactive'):
231
            res = activation_backend.deactivate_user(
232
                user,
233
                reason=options.get('inactive_reason', None))
234
            if res.is_error():
235
                print "Failed to deactivate,", res.message
236
            else:
237
                print "Account %s deactivated" % user.username
238

    
239
        invitations = options.get('invitations')
240
        if invitations is not None:
241
            user.invitations = int(invitations)
242

    
243
        groupname = options.get('add-group')
244
        if groupname is not None:
245
            try:
246
                group = Group.objects.get(name=groupname)
247
                user.groups.add(group)
248
            except Group.DoesNotExist, e:
249
                self.stderr.write(
250
                    "Group named %s does not exist\n" % groupname)
251

    
252
        groupname = options.get('delete-group')
253
        if groupname is not None:
254
            try:
255
                group = Group.objects.get(name=groupname)
256
                user.groups.remove(group)
257
            except Group.DoesNotExist, e:
258
                self.stderr.write(
259
                    "Group named %s does not exist\n" % groupname)
260

    
261
        pname = options.get('add-permission')
262
        if pname is not None:
263
            try:
264
                r, created = add_user_permission(user, pname)
265
                if created:
266
                    self.stderr.write(
267
                        'Permission: %s created successfully\n' % pname)
268
                if r > 0:
269
                    self.stderr.write(
270
                        'Permission: %s added successfully\n' % pname)
271
                elif r == 0:
272
                    self.stderr.write(
273
                        'User has already permission: %s\n' % pname)
274
            except Exception, e:
275
                raise CommandError(e)
276

    
277
        pname = options.get('delete-permission')
278
        if pname is not None and not user.has_perm(pname):
279
            try:
280
                r = remove_user_permission(user, pname)
281
                if r < 0:
282
                    self.stderr.write(
283
                        'Invalid permission codename: %s\n' % pname)
284
                elif r == 0:
285
                    self.stderr.write('User has not permission: %s\n' % pname)
286
                elif r > 0:
287
                    self.stderr.write(
288
                        'Permission: %s removed successfully\n' % pname)
289
            except Exception, e:
290
                raise CommandError(e)
291

    
292
        level = options.get('level')
293
        if level is not None:
294
            user.level = int(level)
295

    
296
        password = options.get('password')
297
        if password is not None:
298
            user.set_password(password)
299

    
300
        password = None
301
        if options['renew_password']:
302
            password = AstakosUser.objects.make_random_password()
303
            user.set_password(password)
304

    
305
        if options['renew_token']:
306
            user.renew_token()
307

    
308
        if options['sign_terms']:
309
            user.has_signed_terms = True
310
            user.date_signed_terms = datetime.now()
311

    
312
        try:
313
            user.save()
314
        except ValidationError, e:
315
            raise CommandError(e)
316

    
317
        if password:
318
            self.stdout.write('User\'s new password: %s\n' % password)
319

    
320
        delete = options.get('delete')
321
        if delete:
322
            if user.is_accepted():
323
                m = "Cannot delete. User %s is accepted." % user
324
                raise CommandError(m)
325
            management.call_command('user-show', str(user.pk),
326
                                    list_quotas=True)
327

    
328
            if not force:
329
                self.stdout.write("About to delete user %s. " % user.uuid)
330
                self.confirm()
331
            user.delete()
332

    
333
        # Change users email address
334
        newemail = options.get('set-email', None)
335
        if newemail is not None:
336
            newemail = newemail.strip()
337
            try:
338
                validate_email(newemail)
339
            except ValidationError:
340
                m = "Invalid email address."
341
                raise CommandError(m)
342

    
343
            if AstakosUser.objects.user_exists(newemail):
344
                m = "A user with this email address already exists."
345
                raise CommandError(m)
346

    
347
            user.set_email(newemail)
348
            user.save()
349

    
350
    def confirm(self):
351
        self.stdout.write("Confirm? [y/N] ")
352
        try:
353
            response = raw_input()
354
        except EOFError:
355
            response = "ABORT"
356
        if string.lower(response) not in ['y', 'yes']:
357
            self.stderr.write("Aborted.\n")
358
            exit()
359

    
360
    def handle_all_users(self, *args, **options):
361
        pass