Merge branch 'feature/delete-user' into 'master'
Feature/delete user See merge request ungleich-public/dynamicweb!701
This commit is contained in:
		
				commit
				
					
						a63d9098d4
					
				
			
		
					 5 changed files with 269 additions and 0 deletions
				
			
		
							
								
								
									
										216
									
								
								datacenterlight/management/commands/deleteuser.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								datacenterlight/management/commands/deleteuser.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,216 @@
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import oca
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import stripe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.core.management.base import BaseCommand
 | 
				
			||||||
 | 
					from membership.models import CustomUser, DeletedUser
 | 
				
			||||||
 | 
					from hosting.models import (
 | 
				
			||||||
 | 
					    HostingOrder, HostingBill, VMDetail, UserCardDetail, UserHostingKey
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					from opennebula_api.models import OpenNebulaManager
 | 
				
			||||||
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def query_yes_no(question, default="yes"):
 | 
				
			||||||
 | 
					    """Ask a yes/no question via raw_input() and return their answer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "question" is a string that is presented to the user.
 | 
				
			||||||
 | 
					    "default" is the presumed answer if the user just hits <Enter>.
 | 
				
			||||||
 | 
					        It must be "yes" (the default), "no" or None (meaning
 | 
				
			||||||
 | 
					        an answer is required of the user).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The "answer" return value is True for "yes" or False for "no".
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    valid = {"yes": True, "y": True, "ye": True,
 | 
				
			||||||
 | 
					             "no": False, "n": False}
 | 
				
			||||||
 | 
					    if default is None:
 | 
				
			||||||
 | 
					        prompt = " [y/n] "
 | 
				
			||||||
 | 
					    elif default == "yes":
 | 
				
			||||||
 | 
					        prompt = " [Y/n] "
 | 
				
			||||||
 | 
					    elif default == "no":
 | 
				
			||||||
 | 
					        prompt = " [y/N] "
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise ValueError("invalid default answer: '%s'" % default)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
 | 
					        sys.stdout.write(question + prompt)
 | 
				
			||||||
 | 
					        choice = input().lower()
 | 
				
			||||||
 | 
					        if default is not None and choice == '':
 | 
				
			||||||
 | 
					            return valid[default]
 | 
				
			||||||
 | 
					        elif choice in valid:
 | 
				
			||||||
 | 
					            return valid[choice]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            sys.stdout.write("Please respond with 'yes' or 'no' "
 | 
				
			||||||
 | 
					                             "(or 'y' or 'n').\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Command(BaseCommand):
 | 
				
			||||||
 | 
					    help = '''Deletes all resources of the user from the project'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_arguments(self, parser):
 | 
				
			||||||
 | 
					        parser.add_argument('customer_email', nargs='+', type=str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            for email in options['customer_email']:
 | 
				
			||||||
 | 
					                r = query_yes_no("Are you sure you want to delete {} ?".format(
 | 
				
			||||||
 | 
					                    email, None
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					                if r:
 | 
				
			||||||
 | 
					                    logger.debug("Deleting user {}".format(email))
 | 
				
			||||||
 | 
					                    # Get stripe customer instance and delete the customer
 | 
				
			||||||
 | 
					                    try:
 | 
				
			||||||
 | 
					                        cus_user = CustomUser.objects.get(email=email)
 | 
				
			||||||
 | 
					                    except CustomUser.DoesNotExist as dne:
 | 
				
			||||||
 | 
					                        logger.error("CustomUser with email {} does "
 | 
				
			||||||
 | 
					                                     "not exist".format(email))
 | 
				
			||||||
 | 
					                        sys.exit(1)
 | 
				
			||||||
 | 
					                    stripe_customer = cus_user.stripecustomer
 | 
				
			||||||
 | 
					                    c = stripe.Customer.retrieve(
 | 
				
			||||||
 | 
					                        stripe_customer.stripe_id
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    cus_delete_obj = c.delete()
 | 
				
			||||||
 | 
					                    if cus_delete_obj.deleted:
 | 
				
			||||||
 | 
					                        logger.debug(
 | 
				
			||||||
 | 
					                            "StripeCustomer {} associated with {} deleted"
 | 
				
			||||||
 | 
					                            "".format(stripe_customer.stripe_id, email)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        logger.error("Error while deleting the StripeCustomer")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    hosting_orders = HostingOrder.objects.filter(
 | 
				
			||||||
 | 
					                        customer=stripe_customer.id
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    vm_ids = []
 | 
				
			||||||
 | 
					                    for order in hosting_orders:
 | 
				
			||||||
 | 
					                        vm_ids.append(order.vm_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Delete Billing Address
 | 
				
			||||||
 | 
					                        if order.billing_address is not None:
 | 
				
			||||||
 | 
					                            order.billing_address.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "Billing Address {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(order.billing_address.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the billing_address")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Delete Order Detail
 | 
				
			||||||
 | 
					                        if order.order_detail is not None:
 | 
				
			||||||
 | 
					                            order.order_detail.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "Order Detail {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(order.order_detail.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the order_detail. None")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Delete order
 | 
				
			||||||
 | 
					                        if order is not None:
 | 
				
			||||||
 | 
					                            order.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "Order {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(order.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the Order")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    hosting_bills = HostingBill.objects.filter(
 | 
				
			||||||
 | 
					                        customer=stripe_customer.id
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete hosting bills
 | 
				
			||||||
 | 
					                    for bill in hosting_bills:
 | 
				
			||||||
 | 
					                        if bill.billing_address is not None:
 | 
				
			||||||
 | 
					                            bill.billing_address.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "HostingBills billing address {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(bill.billing_address.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the HostingBill's Billing address")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if bill is not None:
 | 
				
			||||||
 | 
					                            bill.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "HostingBill {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(bill.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the HostingBill")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete VMDetail
 | 
				
			||||||
 | 
					                    for vm_id in vm_ids:
 | 
				
			||||||
 | 
					                        vm_detail = VMDetail.objects.get(vm_id=vm_id)
 | 
				
			||||||
 | 
					                        if vm_detail is not None:
 | 
				
			||||||
 | 
					                            vm_detail.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "vm_detail {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(vm_detail.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the vm_detail")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete UserCardDetail
 | 
				
			||||||
 | 
					                    ucds = UserCardDetail.objects.filter(
 | 
				
			||||||
 | 
					                        stripe_customer=stripe_customer
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    for ucd in ucds:
 | 
				
			||||||
 | 
					                        if ucd is not None:
 | 
				
			||||||
 | 
					                            ucd.delete()
 | 
				
			||||||
 | 
					                            logger.debug(
 | 
				
			||||||
 | 
					                                "User Card Detail {} associated with {} deleted"
 | 
				
			||||||
 | 
					                                "".format(ucd.id, email)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            logger.error(
 | 
				
			||||||
 | 
					                                "Error while deleting the User Card Detail")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete UserHostingKey
 | 
				
			||||||
 | 
					                    uhks = UserHostingKey.objects.filter(
 | 
				
			||||||
 | 
					                        user=cus_user
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    for uhk in uhks:
 | 
				
			||||||
 | 
					                        uhk.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete stripe customer
 | 
				
			||||||
 | 
					                    stripe_customer.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # add user to deleteduser
 | 
				
			||||||
 | 
					                    DeletedUser.objects.create(
 | 
				
			||||||
 | 
					                        email=cus_user.email, name=cus_user.name,
 | 
				
			||||||
 | 
					                        user_id = cus_user.id
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # delete CustomUser
 | 
				
			||||||
 | 
					                    cus_user.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # remove user from OpenNebula
 | 
				
			||||||
 | 
					                    manager = OpenNebulaManager()
 | 
				
			||||||
 | 
					                    user_pool = manager._get_user_pool()
 | 
				
			||||||
 | 
					                    on_user = user_pool.get_by_name(email)
 | 
				
			||||||
 | 
					                    if on_user.id > 0:
 | 
				
			||||||
 | 
					                        logger.debug(
 | 
				
			||||||
 | 
					                            "Deleting user {} => ID={} from opennebula".format(
 | 
				
			||||||
 | 
					                                email, on_user.id)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        manager.oneadmin_client.call(
 | 
				
			||||||
 | 
					                            oca.User.METHODS['delete'], on_user.id
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        logger.error(
 | 
				
			||||||
 | 
					                            "User not found with email {}. "
 | 
				
			||||||
 | 
					                            "Not doing anything".format(email)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    logger.debug("Deleted {} SUCCESSFULLY.".format(email))
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            print(" *** Error occurred. Details {}".format(str(e)))
 | 
				
			||||||
| 
						 | 
					@ -212,6 +212,12 @@ class UserHostingKey(models.Model):
 | 
				
			||||||
        # self.save(update_fields=['public_key'])
 | 
					        # self.save(update_fields=['public_key'])
 | 
				
			||||||
        return private_key, public_key
 | 
					        return private_key, public_key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete(self,*args,**kwargs):
 | 
				
			||||||
 | 
					        if os.path.isfile(self.private_key.path):
 | 
				
			||||||
 | 
					            os.remove(self.private_key.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super(UserHostingKey, self).delete(*args,**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HostingBill(AssignPermissionsMixin, models.Model):
 | 
					class HostingBill(AssignPermissionsMixin, models.Model):
 | 
				
			||||||
    customer = models.ForeignKey(StripeCustomer)
 | 
					    customer = models.ForeignKey(StripeCustomer)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					from django.db import migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					    dependencies = [('membership', '0007_auto_20180213_0128'),
 | 
				
			||||||
 | 
					                    ('djangocms_blog', '0032_auto_20180109_0023'),
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.RunSQL(
 | 
				
			||||||
 | 
					            "ALTER TABLE djangocms_blog_authorentriesplugin_authors "
 | 
				
			||||||
 | 
					            "RENAME COLUMN user_id TO customuser_id;"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
							
								
								
									
										25
									
								
								membership/migrations/0009_deleteduser.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								membership/migrations/0009_deleteduser.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2019-05-06 06:06
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('membership', '0008_change_user_id_to_customer_id_in_djangocms_blog'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.CreateModel(
 | 
				
			||||||
 | 
					            name='DeletedUser',
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
				
			||||||
 | 
					                ('user_id', models.PositiveIntegerField()),
 | 
				
			||||||
 | 
					                ('name', models.CharField(max_length=254)),
 | 
				
			||||||
 | 
					                ('email', models.EmailField(max_length=254, unique=True)),
 | 
				
			||||||
 | 
					                ('deleted_at', models.DateTimeField(auto_now_add=True)),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -265,6 +265,15 @@ class CreditCards(models.Model):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeletedUser(models.Model):
 | 
				
			||||||
 | 
					    user_id = models.PositiveIntegerField()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # why 254 ? => to be consistent with legacy code
 | 
				
			||||||
 | 
					    name = models.CharField(max_length=254)
 | 
				
			||||||
 | 
					    email = models.EmailField(unique=True, max_length=254)
 | 
				
			||||||
 | 
					    deleted_at = models.DateTimeField(auto_now_add=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Calendar(models.Model):
 | 
					class Calendar(models.Model):
 | 
				
			||||||
    datebooked = models.DateField()
 | 
					    datebooked = models.DateField()
 | 
				
			||||||
    user = models.ForeignKey(CustomUser)
 | 
					    user = models.ForeignKey(CustomUser)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue