From 649509dec1d670eed441feccdf9d03c43d7eb054 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 21 Dec 2016 00:43:52 +0800 Subject: [PATCH] Change models dir --- apps/assets/models.py | 394 -------------------------------- apps/assets/models/__init__.py | 8 + apps/assets/models/asset.py | 127 ++++++++++ apps/assets/models/group.py | 51 +++++ apps/assets/models/idc.py | 61 +++++ apps/assets/models/user.py | 185 +++++++++++++++ apps/assets/models/utils.py | 23 ++ apps/users/models.py | 299 ------------------------ apps/users/models/__init__.py | 6 +- apps/users/models/access_key.py | 23 ++ apps/users/models/group.py | 57 ++++- apps/users/models/user.py | 26 ++- apps/users/models/utils.py | 16 ++ 13 files changed, 568 insertions(+), 708 deletions(-) delete mode 100644 apps/assets/models.py create mode 100644 apps/assets/models/__init__.py create mode 100644 apps/assets/models/asset.py create mode 100644 apps/assets/models/group.py create mode 100644 apps/assets/models/idc.py create mode 100644 apps/assets/models/user.py create mode 100644 apps/assets/models/utils.py delete mode 100644 apps/users/models.py create mode 100644 apps/users/models/access_key.py create mode 100644 apps/users/models/utils.py diff --git a/apps/assets/models.py b/apps/assets/models.py deleted file mode 100644 index aa22a2f02..000000000 --- a/apps/assets/models.py +++ /dev/null @@ -1,394 +0,0 @@ -# coding:utf-8 -from __future__ import unicode_literals, absolute_import - -import functools -from django.db import models -from django.core import serializers -import logging -from django.utils.translation import ugettext_lazy as _ -from django.core.exceptions import ValidationError - -from common.utils import signer, validate_ssh_private_key - -logger = logging.getLogger(__name__) - - -class IDC(models.Model): - name = models.CharField(max_length=32, verbose_name=_('Name')) - bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth')) - contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact')) - phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone')) - address = models.CharField(max_length=128, blank=True, verbose_name=_("Address")) - intranet = models.TextField(blank=True, verbose_name=_('Intranet')) - extranet = models.TextField(blank=True, verbose_name=_('Extranet')) - date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date added')) - operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator')) - created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - - def __unicode__(self): - return self.name - - @classmethod - def initial(cls): - return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default IDC'))[0] - - class Meta: - db_table = 'idc' - - @classmethod - def generate_fake(cls, count=100): - from random import seed, choice - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - idc = cls(name=forgery_py.name.full_name(), - bandwidth='200M', - contact=forgery_py.name.full_name(), - phone=forgery_py.address.phone(), - address=forgery_py.address.city() + forgery_py.address.street_address(), - operator=choice(['北京联通', '北京电信', 'BGP全网通']), - comment=forgery_py.lorem_ipsum.sentence(), - created_by='Fake') - try: - idc.save() - logger.debug('Generate fake asset group: %s' % idc.name) - except IntegrityError: - print('Error continue') - continue - - -def private_key_validator(value): - if not validate_ssh_private_key(value): - raise ValidationError( - _('%(value)s is not an even number'), - params={'value': value}, - ) - - -class AdminUser(models.Model): - name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) - username = models.CharField(max_length=16, verbose_name=_('Username')) - _password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - _private_key = models.CharField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), - validators=[private_key_validator,]) - _public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True, null=True) - created_by = models.CharField(max_length=32, null=True, verbose_name=_('Created by')) - - def __unicode__(self): - return self.name - - @property - def password(self): - return signer.unsign(self._password) - - @password.setter - def password(self, password_raw): - self._password = signer.sign(password_raw) - - @property - def private_key(self): - return signer.unsign(self._private_key) - - @private_key.setter - def private_key(self, private_key_raw): - self._private_key = signer.sign(private_key_raw) - - @property - def public_key(self): - return signer.unsign(self._public_key) - - @public_key.setter - def public_key(self, public_key_raw): - self._public_key = signer.sign(public_key_raw) - - @property - def assets_amount(self): - return self.assets.count() - - class Meta: - db_table = 'admin_user' - - @classmethod - def generate_fake(cls, count=100): - from random import seed - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - obj = cls(name=forgery_py.name.full_name(), - username=forgery_py.internet.user_name(), - password=forgery_py.lorem_ipsum.word(), - comment=forgery_py.lorem_ipsum.sentence(), - created_by='Fake') - try: - obj.save() - logger.debug('Generate fake asset group: %s' % obj.name) - except IntegrityError: - print('Error continue') - continue - - -class SystemUser(models.Model): - PROTOCOL_CHOICES = ( - ('ssh', 'ssh'), - ) - name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) - username = models.CharField(max_length=16, verbose_name=_('Username')) - _password = models.CharField(max_length=256, blank=True, verbose_name=_('Password')) - protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol')) - _private_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH private key')) - _public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key')) - as_default = models.BooleanField(default=False, verbose_name=_('As default')) - auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) - auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key')) - sudo = models.TextField(max_length=4096, default='/user/bin/whoami', verbose_name=_('Sudo')) - shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) - home = models.CharField(max_length=64, blank=True, verbose_name=_('Home')) - uid = models.IntegerField(null=True, blank=True, verbose_name=_('Uid')) - date_created = models.DateTimeField(auto_now_add=True) - created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) - comment = models.TextField(max_length=128, blank=True, verbose_name=_('Comment')) - - def __unicode__(self): - return self.name - - @property - def password(self): - return signer.unsign(self._password) - - @password.setter - def password(self, password_raw): - self._password = signer.sign(password_raw) - - @property - def private_key(self): - return signer.unsign(self._private_key) - - @private_key.setter - def private_key(self, private_key_raw): - self._private_key = signer.sign(private_key_raw) - - @property - def public_key(self): - return signer.unsign(self._public_key) - - @public_key.setter - def public_key(self, public_key_raw): - self._public_key = signer.sign(public_key_raw) - - def get_assets_inherit_from_asset_groups(self): - assets = set() - asset_groups = self.asset_groups.all() - for asset_group in asset_groups: - for asset in asset_group.assets.all(): - setattr(asset, 'is_inherit_from_asset_groups', True) - setattr(asset, 'inherit_from_asset_groups', - getattr(asset, b'inherit_from_asset_groups', set()).add(asset_group)) - assets.add(asset) - return assets - - def get_assets(self): - assets = set(self.assets.all()) | self.get_assets_inherit_from_asset_groups() - return list(assets) - - @property - def assets_amount(self): - return self.assets.count() - - @property - def asset_group_amount(self): - return self.asset_groups.count() - - class Meta: - db_table = 'system_user' - - @classmethod - def generate_fake(cls, count=100): - from random import seed - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - obj = cls(name=forgery_py.name.full_name(), - username=forgery_py.internet.user_name(), - password=forgery_py.lorem_ipsum.word(), - comment=forgery_py.lorem_ipsum.sentence(), - created_by='Fake') - try: - obj.save() - logger.debug('Generate fake asset group: %s' % obj.name) - except IntegrityError: - print('Error continue') - continue - - -class AssetGroup(models.Model): - name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) - system_users = models.ManyToManyField(SystemUser, related_name='asset_groups', blank=True) - created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) - date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date added')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - - def __unicode__(self): - return self.name - - class Meta: - db_table = 'asset_group' - - @classmethod - def initial(cls): - asset_group = cls(name=_('Default'), comment=_('Default asset group')) - asset_group.save() - - @classmethod - def generate_fake(cls, count=100): - from random import seed - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - group = cls(name=forgery_py.name.full_name(), - comment=forgery_py.lorem_ipsum.sentence(), - created_by='Fake') - try: - group.save() - logger.debug('Generate fake asset group: %s' % group.name) - except IntegrityError: - print('Error continue') - continue - - -def get_default_idc(): - return IDC.initial() - - -class Asset(models.Model): - STATUS_CHOICES = ( - ('In use', _('In use')), - ('Out of use', _('Out of use')), - ) - TYPE_CHOICES = ( - ('Server', _('Server')), - ('VM', _('VM')), - ('Switch', _('Switch')), - ('Router', _('Router')), - ('Firewall', _('Firewall')), - ('Storage', _("Storage")), - ) - ENV_CHOICES = ( - ('Prod', 'Production'), - ('Dev', 'Development'), - ('Test', 'Testing'), - ) - - ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) - other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP')) - remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP')) - hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) - port = models.IntegerField(default=22, verbose_name=_('Port')) - groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups')) - admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets', - on_delete=models.SET_NULL, verbose_name=_("Admin user")) - system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User")) - idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets', - on_delete=models.SET_NULL, verbose_name=_('IDC'),) - mac_address = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address")) - brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand')) - cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('CPU')) - memory = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Memory')) - disk = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk')) - os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS')) - cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number')) - cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position')) - number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number')) - status = models.CharField(choices=STATUS_CHOICES, max_length=8, null=True, blank=True, - default='In use', verbose_name=_('Asset status')) - type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, - default='Server', verbose_name=_('Asset type'),) - env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, - default='Prod', verbose_name=_('Asset environment'),) - sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number')) - created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) - is_active = models.BooleanField(default=True, verbose_name=_('Is active')) - date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added')) - comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) - tags = models.ManyToManyField('Tag', blank=True, verbose_name=_('Tags')) - - def __unicode__(self): - return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port} - - @property - def is_valid(self): - warning = '' - if not self.is_active: - warning += ' inactive' - else: - return True, '' - return False, warning - - def json(self): - pass - - class Meta: - db_table = 'asset' - unique_together = ('ip', 'port') - - @classmethod - def generate_fake(cls, count=100): - from random import seed, choice - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - asset = cls(ip='%s.%s.%s.%s' % (i, i, i, i), - hostname=forgery_py.internet.user_name(True), - admin_user=choice(AdminUser.objects.all()), - idc=choice(IDC.objects.all()), - port=22, - created_by='Fake') - try: - asset.save() - asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)] - asset.groups = [choice(AssetGroup.objects.all()) for i in range(3)] - logger.debug('Generate fake asset : %s' % asset.ip) - except IntegrityError: - print('Error continue') - continue - - -class Tag(models.Model): - name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) - created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) - created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) - - def __unicode__(self): - return self.name - - __str__ = __unicode__ - - class Meta: - db_table = 'tag' - - -def init_all_models(): - for cls in (AssetGroup,): - cls.initial() - - -def generate_fake(): - for cls in (AssetGroup, IDC, AdminUser, SystemUser, Asset): - cls.generate_fake() - - -def flush_all(): - for cls in (AssetGroup, IDC, AdminUser, SystemUser, Asset): - cls.objects.all().delete() diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py new file mode 100644 index 000000000..5ee3050c4 --- /dev/null +++ b/apps/assets/models/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from .idc import * +from .user import * +from .group import * +from .asset import * diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py new file mode 100644 index 000000000..39f0f5dc6 --- /dev/null +++ b/apps/assets/models/asset.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from __future__ import unicode_literals + +from django.db import models +import logging +from django.utils.translation import ugettext_lazy as _ + +from . import IDC, AssetGroup, AdminUser, SystemUser + +__all__ = ['Asset', 'Tag'] +logger = logging.getLogger(__name__) + + +def get_default_idc(): + return IDC.initial() + + +class Asset(models.Model): + STATUS_CHOICES = ( + ('In use', _('In use')), + ('Out of use', _('Out of use')), + ) + TYPE_CHOICES = ( + ('Server', _('Server')), + ('VM', _('VM')), + ('Switch', _('Switch')), + ('Router', _('Router')), + ('Firewall', _('Firewall')), + ('Storage', _("Storage")), + ) + ENV_CHOICES = ( + ('Prod', 'Production'), + ('Dev', 'Development'), + ('Test', 'Testing'), + ) + + ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) + other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP')) + remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP')) + hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) + port = models.IntegerField(default=22, verbose_name=_('Port')) + groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups')) + admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets', + on_delete=models.SET_NULL, verbose_name=_("Admin user")) + system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User")) + idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets', + on_delete=models.SET_NULL, verbose_name=_('IDC'),) + mac_address = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address")) + brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand')) + cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('CPU')) + memory = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Memory')) + disk = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk')) + os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS')) + cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number')) + cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position')) + number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number')) + status = models.CharField(choices=STATUS_CHOICES, max_length=8, null=True, blank=True, + default='In use', verbose_name=_('Asset status')) + type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, + default='Server', verbose_name=_('Asset type'),) + env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, + default='Prod', verbose_name=_('Asset environment'),) + sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number')) + created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) + is_active = models.BooleanField(default=True, verbose_name=_('Is active')) + date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added')) + comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) + tags = models.ManyToManyField('Tag', blank=True, verbose_name=_('Tags')) + + def __unicode__(self): + return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port} + + @property + def is_valid(self): + warning = '' + if not self.is_active: + warning += ' inactive' + else: + return True, '' + return False, warning + + def json(self): + pass + + class Meta: + db_table = 'asset' + unique_together = ('ip', 'port') + + @classmethod + def generate_fake(cls, count=100): + from random import seed, choice + import forgery_py + from django.db import IntegrityError + + seed() + for i in range(count): + asset = cls(ip='%s.%s.%s.%s' % (i, i, i, i), + hostname=forgery_py.internet.user_name(True), + admin_user=choice(AdminUser.objects.all()), + idc=choice(IDC.objects.all()), + port=22, + created_by='Fake') + try: + asset.save() + asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)] + asset.groups = [choice(AssetGroup.objects.all()) for i in range(3)] + logger.debug('Generate fake asset : %s' % asset.ip) + except IntegrityError: + print('Error continue') + continue + + +class Tag(models.Model): + name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) + created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) + created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) + + def __unicode__(self): + return self.name + + __str__ = __unicode__ + + class Meta: + db_table = 'tag' \ No newline at end of file diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py new file mode 100644 index 000000000..6502208ac --- /dev/null +++ b/apps/assets/models/group.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from __future__ import unicode_literals + +from django.db import models +import logging +from django.utils.translation import ugettext_lazy as _ + +from . import SystemUser + +__all__ = ['AssetGroup'] +logger = logging.getLogger(__name__) + + +class AssetGroup(models.Model): + name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) + system_users = models.ManyToManyField(SystemUser, related_name='asset_groups', blank=True) + created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) + date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date added')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + + def __unicode__(self): + return self.name + + class Meta: + db_table = 'asset_group' + + @classmethod + def initial(cls): + asset_group = cls(name=_('Default'), comment=_('Default asset group')) + asset_group.save() + + @classmethod + def generate_fake(cls, count=100): + from random import seed + import forgery_py + from django.db import IntegrityError + + seed() + for i in range(count): + group = cls(name=forgery_py.name.full_name(), + comment=forgery_py.lorem_ipsum.sentence(), + created_by='Fake') + try: + group.save() + logger.debug('Generate fake asset group: %s' % group.name) + except IntegrityError: + print('Error continue') + continue diff --git a/apps/assets/models/idc.py b/apps/assets/models/idc.py new file mode 100644 index 000000000..b66519876 --- /dev/null +++ b/apps/assets/models/idc.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from __future__ import unicode_literals + +from django.db import models +import logging +from django.utils.translation import ugettext_lazy as _ + + +__all__ = ['IDC'] +logger = logging.getLogger(__name__) + + +class IDC(models.Model): + name = models.CharField(max_length=32, verbose_name=_('Name')) + bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth')) + contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact')) + phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone')) + address = models.CharField(max_length=128, blank=True, verbose_name=_("Address")) + intranet = models.TextField(blank=True, verbose_name=_('Intranet')) + extranet = models.TextField(blank=True, verbose_name=_('Extranet')) + date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date added')) + operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator')) + created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + + def __unicode__(self): + return self.name + + @classmethod + def initial(cls): + return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default IDC'))[0] + + class Meta: + db_table = 'idc' + + @classmethod + def generate_fake(cls, count=100): + from random import seed, choice + import forgery_py + from django.db import IntegrityError + + seed() + for i in range(count): + idc = cls(name=forgery_py.name.full_name(), + bandwidth='200M', + contact=forgery_py.name.full_name(), + phone=forgery_py.address.phone(), + address=forgery_py.address.city() + forgery_py.address.street_address(), + operator=choice(['北京联通', '北京电信', 'BGP全网通']), + comment=forgery_py.lorem_ipsum.sentence(), + created_by='Fake') + try: + idc.save() + logger.debug('Generate fake asset group: %s' % idc.name) + except IntegrityError: + print('Error continue') + continue + diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py new file mode 100644 index 000000000..92aa10d67 --- /dev/null +++ b/apps/assets/models/user.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from __future__ import unicode_literals + +from django.db import models +import logging +from django.utils.translation import ugettext_lazy as _ +from django.core.exceptions import ValidationError + +from common.utils import signer, validate_ssh_private_key + +__all__ = ['AdminUser', 'SystemUser', 'private_key_validator'] +logger = logging.getLogger(__name__) + + +def private_key_validator(value): + if not validate_ssh_private_key(value): + raise ValidationError( + _('%(value)s is not an even number'), + params={'value': value}, + ) + + +class AdminUser(models.Model): + name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) + username = models.CharField(max_length=16, verbose_name=_('Username')) + _password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) + _private_key = models.CharField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), + validators=[private_key_validator,]) + _public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + date_created = models.DateTimeField(auto_now_add=True, null=True) + created_by = models.CharField(max_length=32, null=True, verbose_name=_('Created by')) + + def __unicode__(self): + return self.name + + @property + def password(self): + return signer.unsign(self._password) + + @password.setter + def password(self, password_raw): + self._password = signer.sign(password_raw) + + @property + def private_key(self): + return signer.unsign(self._private_key) + + @private_key.setter + def private_key(self, private_key_raw): + self._private_key = signer.sign(private_key_raw) + + @property + def public_key(self): + return signer.unsign(self._public_key) + + @public_key.setter + def public_key(self, public_key_raw): + self._public_key = signer.sign(public_key_raw) + + @property + def assets_amount(self): + return self.assets.count() + + class Meta: + db_table = 'admin_user' + + @classmethod + def generate_fake(cls, count=100): + from random import seed + import forgery_py + from django.db import IntegrityError + + seed() + for i in range(count): + obj = cls(name=forgery_py.name.full_name(), + username=forgery_py.internet.user_name(), + password=forgery_py.lorem_ipsum.word(), + comment=forgery_py.lorem_ipsum.sentence(), + created_by='Fake') + try: + obj.save() + logger.debug('Generate fake asset group: %s' % obj.name) + except IntegrityError: + print('Error continue') + continue + + +class SystemUser(models.Model): + PROTOCOL_CHOICES = ( + ('ssh', 'ssh'), + ) + name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) + username = models.CharField(max_length=16, verbose_name=_('Username')) + _password = models.CharField(max_length=256, blank=True, verbose_name=_('Password')) + protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol')) + _private_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH private key')) + _public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key')) + as_default = models.BooleanField(default=False, verbose_name=_('As default')) + auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) + auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key')) + sudo = models.TextField(max_length=4096, default='/user/bin/whoami', verbose_name=_('Sudo')) + shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) + home = models.CharField(max_length=64, blank=True, verbose_name=_('Home')) + uid = models.IntegerField(null=True, blank=True, verbose_name=_('Uid')) + date_created = models.DateTimeField(auto_now_add=True) + created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) + comment = models.TextField(max_length=128, blank=True, verbose_name=_('Comment')) + + def __unicode__(self): + return self.name + + @property + def password(self): + return signer.unsign(self._password) + + @password.setter + def password(self, password_raw): + self._password = signer.sign(password_raw) + + @property + def private_key(self): + return signer.unsign(self._private_key) + + @private_key.setter + def private_key(self, private_key_raw): + self._private_key = signer.sign(private_key_raw) + + @property + def public_key(self): + return signer.unsign(self._public_key) + + @public_key.setter + def public_key(self, public_key_raw): + self._public_key = signer.sign(public_key_raw) + + def get_assets_inherit_from_asset_groups(self): + assets = set() + asset_groups = self.asset_groups.all() + for asset_group in asset_groups: + for asset in asset_group.assets.all(): + setattr(asset, 'is_inherit_from_asset_groups', True) + setattr(asset, 'inherit_from_asset_groups', + getattr(asset, b'inherit_from_asset_groups', set()).add(asset_group)) + assets.add(asset) + return assets + + def get_assets(self): + assets = set(self.assets.all()) | self.get_assets_inherit_from_asset_groups() + return list(assets) + + @property + def assets_amount(self): + return self.assets.count() + + @property + def asset_group_amount(self): + return self.asset_groups.count() + + class Meta: + db_table = 'system_user' + + @classmethod + def generate_fake(cls, count=100): + from random import seed + import forgery_py + from django.db import IntegrityError + + seed() + for i in range(count): + obj = cls(name=forgery_py.name.full_name(), + username=forgery_py.internet.user_name(), + password=forgery_py.lorem_ipsum.word(), + comment=forgery_py.lorem_ipsum.sentence(), + created_by='Fake') + try: + obj.save() + logger.debug('Generate fake asset group: %s' % obj.name) + except IntegrityError: + print('Error continue') + continue + diff --git a/apps/assets/models/utils.py b/apps/assets/models/utils.py new file mode 100644 index 000000000..fc78ea39c --- /dev/null +++ b/apps/assets/models/utils.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from . import IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag + +__all__ = ['initial', 'generate_fake'] + + +def initial(): + for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag]: + if hasattr(cls, 'initial'): + cls.initial() + + +def generate_fake(): + for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag]: + if hasattr(cls, 'generake_fake'): + cls.generake_fake() + + +if __name__ == '__main__': + pass diff --git a/apps/users/models.py b/apps/users/models.py deleted file mode 100644 index 35178003e..000000000 --- a/apps/users/models.py +++ /dev/null @@ -1,299 +0,0 @@ -# ~*~ coding: utf-8 ~*~ - -from __future__ import unicode_literals -from collections import OrderedDict - -from django.contrib.auth.hashers import make_password -from django.contrib.auth.models import AbstractUser -from django.core import signing -from django.db import models, IntegrityError -from django.utils.translation import ugettext_lazy as _ -from django.utils import timezone -from django.shortcuts import reverse - -from rest_framework.authtoken.models import Token - -from common.utils import signer, date_expired_default -from common.mixins import NoDeleteModelMixin - - -class UserGroup(NoDeleteModelMixin): - name = models.CharField(max_length=100, unique=True, verbose_name=_('Name')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True) - created_by = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - - def has_member(self, user): - if user in self.users.all(): - return True - return False - - def delete(self): - if self.name != 'Default': - self.users.clear() - return super(UserGroup, self).delete() - return True - - class Meta: - db_table = 'user_group' - - @classmethod - def initial(cls): - group, created = cls.objects.get_or_create(name='Default', comment='Default user group for all user', - created_by='System') - return group - - @classmethod - def generate_fake(cls, count=100): - from random import seed, choice - import forgery_py - - seed() - for i in range(count): - group = cls(name=forgery_py.name.full_name(), - comment=forgery_py.lorem_ipsum.sentence(), - created_by=choice(User.objects.all()).username) - try: - group.save() - except IntegrityError: - print('Error continue') - continue - - -class User(AbstractUser): - ROLE_CHOICES = ( - ('Admin', _('Administrator')), - ('User', _('User')), - ('APP', _('Application')) - ) - - username = models.CharField(max_length=20, unique=True, verbose_name=_('Username')) - name = models.CharField(max_length=20, verbose_name=_('Name')) - email = models.EmailField(max_length=30, unique=True, verbose_name=_('Email')) - groups = models.ManyToManyField(UserGroup, related_name='users', blank=True, verbose_name=_('User group')) - role = models.CharField(choices=ROLE_CHOICES, default='User', max_length=10, blank=True, verbose_name=_('Role')) - avatar = models.ImageField(upload_to="avatar", verbose_name=_('Avatar')) - wechat = models.CharField(max_length=30, blank=True, verbose_name=_('Wechat')) - phone = models.CharField(max_length=20, blank=True, null=True, verbose_name=_('Phone')) - enable_otp = models.BooleanField(default=False, verbose_name=_('Enable OTP')) - secret_key_otp = models.CharField(max_length=16, blank=True) - _private_key = models.CharField(max_length=5000, blank=True, verbose_name=_('ssh private key')) - _public_key = models.CharField(max_length=1000, blank=True, verbose_name=_('ssh public key')) - comment = models.TextField(max_length=200, blank=True, verbose_name=_('Comment')) - is_first_login = models.BooleanField(default=False) - date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True, - verbose_name=_('Date expired')) - created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by')) - - @property - def password_raw(self): - raise AttributeError('Password raw is not readable attribute') - - #: Use this attr to set user object password, example - #: user = User(username='example', password_raw='password', ...) - #: It's equal: - #: user = User(username='example', ...) - #: user.set_password('password') - @password_raw.setter - def password_raw(self, password_raw_): - self.set_password(password_raw_) - - def get_absolute_url(self): - return reverse('users:user-detail', args=(self.id,)) - - @property - def is_expired(self): - if self.date_expired > timezone.now(): - return False - else: - return True - - @property - def is_valid(self): - if self.is_active and not self.is_expired: - return True - return False - - @property - def private_key(self): - return signer.unsign(self._private_key) - - @private_key.setter - def private_key(self, private_key_raw): - self._private_key = signer.sign(private_key_raw) - - @property - def public_key(self): - return signer.unsign(self._public_key) - - @public_key.setter - def public_key(self, public_key_raw): - self._public_key = signer.sign(public_key_raw) - - @property - def is_superuser(self): - if self.role == 'Admin': - return True - else: - return False - - @property - def is_terminal(self): - return False - - @is_superuser.setter - def is_superuser(self, value): - if value is True: - self.role = 'Admin' - else: - self.role = 'User' - - @property - def is_staff(self): - if self.is_authenticated and self.is_valid: - return True - else: - return False - - @is_staff.setter - def is_staff(self, value): - pass - - def save(self, *args, **kwargs): - if not self.name: - self.name = self.username - - super(User, self).save(*args, **kwargs) - # Add the current user to the default group. - if not self.groups.count(): - group = UserGroup.initial() - self.groups.add(group) - - @property - def private_token(self): - return self.get_private_token() - - def get_private_token(self): - try: - token = Token.objects.get(user=self) - except Token.DoesNotExist: - token = Token.objects.create(user=self) - return token.key - - def refresh_private_token(self): - Token.objects.filter(user=self).delete() - return Token.objects.create(user=self) - - def is_member_of(self, user_group): - if user_group in self.groups.all(): - return True - return False - - def check_public_key(self, public_key): - if self.public_key == public_key: - return True - return False - - def generate_reset_token(self): - return signer.sign_t({'reset': self.id, 'email': self.email}, expires_in=3600) - - def to_json(self): - return OrderedDict({ - 'id': self.id, - 'username': self.username, - 'name': self.name, - 'email': self.email, - 'is_active': self.is_active, - 'is_superuser': self.is_superuser, - 'role': self.get_role_display(), - 'groups': [group.name for group in self.groups.all()], - 'wechat': self.wechat, - 'phone': self.phone, - 'comment': self.comment, - 'date_expired': self.date_expired.strftime('%Y-%m-%d %H:%M:%S') - }) - - @classmethod - def validate_reset_token(cls, token): - try: - data = signer.unsign_t(token) - user_id = data.get('reset', None) - user_email = data.get('email', '') - user = cls.objects.get(id=user_id, email=user_email) - - except (signing.BadSignature, cls.DoesNotExist): - user = None - return user - - def reset_password(self, new_password): - self.set_password(new_password) - self.save() - - class Meta: - db_table = 'user' - - #: Use this method initial user - @classmethod - def initial(cls): - user = cls(username='admin', - email='admin@jumpserver.org', - name=_('Administrator'), - password_raw='admin', - role='Admin', - comment=_('Administrator is the super user of system'), - created_by=_('System')) - user.save() - user.groups.add(UserGroup.initial()) - - def delete(self): - if self.pk == 1 or self.username == 'admin': - return - return super(User, self).delete() - - @classmethod - def generate_fake(cls, count=100): - from random import seed, choice - import forgery_py - from django.db import IntegrityError - - seed() - for i in range(count): - user = cls(username=forgery_py.internet.user_name(True), - email=forgery_py.internet.email_address(), - name=forgery_py.name.full_name(), - password=make_password(forgery_py.lorem_ipsum.word()), - role=choice(dict(User.ROLE_CHOICES).keys()), - wechat=forgery_py.internet.user_name(True), - comment=forgery_py.lorem_ipsum.sentence(), - created_by=choice(cls.objects.all()).username) - try: - user.save() - except IntegrityError: - print('Duplicate Error, continue ...') - continue - user.groups.add(choice(UserGroup.objects.all())) - user.save() - - -def init_all_models(): - for model in (UserGroup, User): - if hasattr(model, 'initial'): - model.initial() - - -def generate_fake(): - for model in (UserGroup, User): - if hasattr(model, 'generate_fake'): - model.generate_fake() - - -# @receiver(post_save, sender=settings.AUTH_USER_MODEL) -# def create_auth_token(sender, instance=None, created=False, **kwargs): -# if created: -# try: -# Token.objects.create(user=instance) -# except IntegrityError: -# pass diff --git a/apps/users/models/__init__.py b/apps/users/models/__init__.py index f93d0bec7..6067e6815 100644 --- a/apps/users/models/__init__.py +++ b/apps/users/models/__init__.py @@ -2,6 +2,8 @@ # -*- coding: utf-8 -*- # +from .group import * +from .user import * +from .access_key import * + -if __name__ == '__main__': - pass diff --git a/apps/users/models/access_key.py b/apps/users/models/access_key.py new file mode 100644 index 000000000..afb42b250 --- /dev/null +++ b/apps/users/models/access_key.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +import uuid + +from django.db import models +from . import User + + +def get_uuid_string(): + return uuid.uuid4().__str__() + + +class AccessKey(models.Model): + id = models.UUIDField(verbose_name='AccessKeyID', primary_key=True, default=get_uuid_string, editable=False) + secret = models.UUIDField(verbose_name='AccessKeySecret', default=get_uuid_string, editable=False) + user = models.ForeignKey(User, verbose_name='User') + + def __unicode__(self): + return self.id + + __str__ = __unicode__ diff --git a/apps/users/models/group.py b/apps/users/models/group.py index 0133d394f..32c8bc4cb 100644 --- a/apps/users/models/group.py +++ b/apps/users/models/group.py @@ -1,5 +1,60 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# +# + +from __future__ import unicode_literals + +from django.db import models, IntegrityError +from django.utils.translation import ugettext_lazy as _ + +from common.utils import signer, date_expired_default +from common.mixins import NoDeleteModelMixin + +__all__ = ['UserGroup'] +class UserGroup(NoDeleteModelMixin): + name = models.CharField(max_length=100, unique=True, verbose_name=_('Name')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + date_created = models.DateTimeField(auto_now_add=True) + created_by = models.CharField(max_length=100) + + def __unicode__(self): + return self.name + + def has_member(self, user): + if user in self.users.all(): + return True + return False + + def delete(self): + if self.name != 'Default': + self.users.clear() + return super(UserGroup, self).delete() + return True + + class Meta: + db_table = 'user_group' + + @classmethod + def initial(cls): + group, created = cls.objects.get_or_create(name='Default', comment='Default user group for all user', + created_by='System') + return group + + @classmethod + def generate_fake(cls, count=100): + from random import seed, choice + import forgery_py + from . import User + + seed() + for i in range(count): + group = cls(name=forgery_py.name.full_name(), + comment=forgery_py.lorem_ipsum.sentence(), + created_by=choice(User.objects.all()).username) + try: + group.save() + except IntegrityError: + print('Error continue') + continue diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 367e37d35..470586c76 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -11,11 +11,13 @@ from django.db import models, IntegrityError from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from django.shortcuts import reverse - from rest_framework.authtoken.models import Token from common.utils import signer, date_expired_default -from common.mixins import NoDeleteModelMixin +from . import UserGroup + + +__all__ = ['User'] class User(AbstractUser): @@ -45,7 +47,7 @@ class User(AbstractUser): @property def password_raw(self): - raise AttributeError('Password raw is not readable attribute') + raise AttributeError('Password raw is not a readable attribute') #: Use this attr to set user object password, example #: user = User(username='example', password_raw='password', ...) @@ -61,10 +63,10 @@ class User(AbstractUser): @property def is_expired(self): - if self.date_expired > timezone.now(): - return False - else: + if self.date_expired < timezone.now(): return True + else: + return False @property def is_valid(self): @@ -148,7 +150,7 @@ class User(AbstractUser): return False def check_public_key(self, public_key): - if self.public_key == public_key: + if self.ssH_public_key == public_key: return True return False @@ -187,6 +189,11 @@ class User(AbstractUser): self.set_password(new_password) self.save() + def delete(self): + if self.pk == 1 or self.username == 'admin': + return + return super(User, self).delete() + class Meta: db_table = 'user' @@ -203,11 +210,6 @@ class User(AbstractUser): user.save() user.groups.add(UserGroup.initial()) - def delete(self): - if self.pk == 1 or self.username == 'admin': - return - return super(User, self).delete() - @classmethod def generate_fake(cls, count=100): from random import seed, choice diff --git a/apps/users/models/utils.py b/apps/users/models/utils.py new file mode 100644 index 000000000..7dd8f7d25 --- /dev/null +++ b/apps/users/models/utils.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +from . import User, UserGroup + + +def initial_model(): + for cls in [User, UserGroup]: + cls.initial() + + +def generate_fake(): + for cls in [User, UserGroup]: + cls.generate_fake() +