From 5b4ce709af40cdb3b07d558ce49c29df32cc4c5a Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 22 Dec 2016 00:36:31 +0800 Subject: [PATCH] Add private token and change user group --- apps/assets/models/asset.py | 5 ++-- apps/assets/models/group.py | 2 +- apps/assets/models/idc.py | 2 +- apps/assets/models/user.py | 6 ++-- apps/jumpserver/settings.py | 1 - apps/terminal/api.py | 12 ++++++++ apps/terminal/forms.py | 2 +- apps/terminal/models.py | 43 +++++++++++++++++++++++------ apps/users/models/__init__.py | 4 +-- apps/users/models/access_key.py | 23 --------------- apps/users/models/authentication.py | 40 +++++++++++++++++++++++++++ apps/users/models/group.py | 6 ++-- apps/users/models/user.py | 9 +++--- apps/users/models/utils.py | 7 +++-- 14 files changed, 109 insertions(+), 53 deletions(-) delete mode 100644 apps/users/models/access_key.py create mode 100644 apps/users/models/authentication.py diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index e9e990cdf..f38ca798b 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -73,7 +73,7 @@ class Asset(models.Model): def __unicode__(self): return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port} - __str__ = __unicode__() + __str__ = __unicode__ @property def is_valid(self): @@ -88,7 +88,6 @@ class Asset(models.Model): pass class Meta: - db_table = 'asset' unique_together = ('ip', 'port') @classmethod @@ -126,4 +125,4 @@ class Tag(models.Model): __str__ = __unicode__ class Meta: - db_table = 'tag' \ No newline at end of file + ordering = ['name'] diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py index 6502208ac..dfae079f4 100644 --- a/apps/assets/models/group.py +++ b/apps/assets/models/group.py @@ -25,7 +25,7 @@ class AssetGroup(models.Model): return self.name class Meta: - db_table = 'asset_group' + ordering = ['name'] @classmethod def initial(cls): diff --git a/apps/assets/models/idc.py b/apps/assets/models/idc.py index b66519876..18ccc642d 100644 --- a/apps/assets/models/idc.py +++ b/apps/assets/models/idc.py @@ -34,7 +34,7 @@ class IDC(models.Model): return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default IDC'))[0] class Meta: - db_table = 'idc' + ordering = ['name'] @classmethod def generate_fake(cls, count=100): diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 92aa10d67..0e9af99de 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -37,6 +37,8 @@ class AdminUser(models.Model): def __unicode__(self): return self.name + __str__ = __unicode__ + @property def password(self): return signer.unsign(self._password) @@ -66,7 +68,7 @@ class AdminUser(models.Model): return self.assets.count() class Meta: - db_table = 'admin_user' + ordering = ['name'] @classmethod def generate_fake(cls, count=100): @@ -161,7 +163,7 @@ class SystemUser(models.Model): return self.asset_groups.count() class Meta: - db_table = 'system_user' + ordering = ['name'] @classmethod def generate_fake(cls, count=100): diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index aa418fee8..927edfd21 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -60,7 +60,6 @@ INSTALLED_APPS = [ 'common.apps.CommonConfig', 'terminal.apps.TerminalConfig', 'rest_framework', - 'rest_framework.authtoken', 'bootstrapform', 'captcha', 'django.contrib.auth', diff --git a/apps/terminal/api.py b/apps/terminal/api.py index e3113d0b0..d51563223 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -14,6 +14,18 @@ from .serializers import TerminalSerializer, TerminalHeatbeatSerializer from .hands import IsSuperUserOrTerminalUser, User +class TerminalRegister(ListCreateAPIView): + queryset = Terminal.objects.all() + serializer_class = TerminalSerializer + permission_classes = (AllowAny,) + + def create(self, request, *args, **kwargs): + name = signer.unsign(request.data.get('name', '')) + remote_addr = request.Meta.get('REMOTE_ADDR') + serializer = self.serializer_class({'name': name, 'remote_addr': remote_addr}) + + + class TerminalViewSet(viewsets.ModelViewSet): queryset = Terminal.objects.all() diff --git a/apps/terminal/forms.py b/apps/terminal/forms.py index dfc6787c9..823f2e8a7 100644 --- a/apps/terminal/forms.py +++ b/apps/terminal/forms.py @@ -10,7 +10,7 @@ from .models import Terminal class TerminalForm(forms.ModelForm): class Meta: model = Terminal - fields = ['name', 'ip', 'is_active', 'type', 'url', 'comment'] + fields = ['name', 'remote_addr', 'type', 'url', 'comment'] help_texts = { 'url': 'Example: ssh://192.168.1.1:22 or http://jms.jumpserver.org, that user login' } diff --git a/apps/terminal/models.py b/apps/terminal/models.py index 8b65ed6da..07166e6b1 100644 --- a/apps/terminal/models.py +++ b/apps/terminal/models.py @@ -8,20 +8,42 @@ from users.models import User class Terminal(models.Model): TYPE_CHOICES = ( - ('S', 'SSH Terminal'), - ('WT', 'Web Terminal') + ('SSH', 'SSH Terminal'), + ('Web', 'Web Terminal') ) name = models.CharField(max_length=30, unique=True, verbose_name=_('Name')) - ip = models.GenericIPAddressField(verbose_name=_('From ip')) - is_active = models.BooleanField(default=False, verbose_name=_('Is active')) - is_bound_ip = models.BooleanField(default=False, verbose_name=_('Is bound ip')) + remote_addr = models.GenericIPAddressField(verbose_name=_('Remote address'), blank=True, null=True) type = models.CharField(choices=TYPE_CHOICES, max_length=2, verbose_name=_('Terminal type')) + user = models.OneToOneField(User, verbose_name='Application user', null=True) url = models.CharField(max_length=100, verbose_name=_('URL to login')) date_created = models.DateTimeField(auto_now_add=True) comment = models.TextField(blank=True, verbose_name=_('Comment')) - def is_valid(self): - return self.is_active and self.is_accepted + @property + def is_active(self): + if self.user and self.user.is_active: + return True + return False + + @is_active.setter + def is_active(self, active): + if self.user: + self.user.is_active = active + self.user.save() + + @property + def is_accepted(self): + if self.user: + return True + else: + return False + + @is_accepted.setter + def is_accepted(self, accepted): + if accepted: + user = User.create_app_user(name=self.name, comment=self.comment) + self.user = user + self.save() @property def is_superuser(self): @@ -31,9 +53,14 @@ class Terminal(models.Model): def is_terminal(self): return True + def __unicode__(self): + active = 'Active' if self.user and self.user.is_active else 'Disabled' + return '%s: %s' % (self.name, active) + + __str__ = __unicode__ + class Meta: db_table = 'terminal' - ordering = ['is_active'] class TerminalHeatbeat(models.Model): diff --git a/apps/users/models/__init__.py b/apps/users/models/__init__.py index 6067e6815..9cdf1d61d 100644 --- a/apps/users/models/__init__.py +++ b/apps/users/models/__init__.py @@ -4,6 +4,4 @@ from .group import * from .user import * -from .access_key import * - - +from .authentication import * diff --git a/apps/users/models/access_key.py b/apps/users/models/access_key.py deleted file mode 100644 index afb42b250..000000000 --- a/apps/users/models/access_key.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/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/authentication.py b/apps/users/models/authentication.py new file mode 100644 index 000000000..bd68060e1 --- /dev/null +++ b/apps/users/models/authentication.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# + +import uuid +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from rest_framework.authtoken.models import Token +from . import User + +__all__ = ['AccessKey'] + +def get_uuid_string(): + return uuid.uuid4().__str__() + + +class AccessKey(models.Model): + id = models.UUIDField(verbose_name='AccessKeyID', primary_key=True, + default=uuid.uuid4, editable=False) + secret = models.UUIDField(verbose_name='AccessKeySecret', + default=uuid.uuid4, editable=False) + user = models.ForeignKey(User, verbose_name='User', related_name='access_key') + + def get_id(self): + return str(self.id) + + def get_secret(self): + return str(self.secret) + + def __unicode__(self): + return str(self.id) + + __str__ = __unicode__ + + +class PrivateToken(Token): + """Inherit from auth token, otherwise migration is boring""" + + class Meta: + verbose_name = _('Private Token') diff --git a/apps/users/models/group.py b/apps/users/models/group.py index 32c8bc4cb..33ec5d4fe 100644 --- a/apps/users/models/group.py +++ b/apps/users/models/group.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from django.db import models, IntegrityError +from django.contrib.auth.models import Group from django.utils.translation import ugettext_lazy as _ from common.utils import signer, date_expired_default @@ -13,8 +14,7 @@ from common.mixins import NoDeleteModelMixin __all__ = ['UserGroup'] -class UserGroup(NoDeleteModelMixin): - name = models.CharField(max_length=100, unique=True, verbose_name=_('Name')) +class UserGroup(NoDeleteModelMixin, Group): comment = models.TextField(blank=True, verbose_name=_('Comment')) date_created = models.DateTimeField(auto_now_add=True) created_by = models.CharField(max_length=100) @@ -34,7 +34,7 @@ class UserGroup(NoDeleteModelMixin): return True class Meta: - db_table = 'user_group' + ordering = ['name'] @classmethod def initial(cls): diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 0de3474fa..504ce403b 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -15,7 +15,7 @@ from django.shortcuts import reverse from rest_framework.authtoken.models import Token from common.utils import signer, date_expired_default -from . import UserGroup, AccessKey +from . import UserGroup __all__ = ['User'] @@ -178,11 +178,12 @@ class User(AbstractUser): @classmethod def create_app_user(cls, name, comment): - domain_name = settings.DOMAIN_NAME or 'jumpserver.org' + from . import AccessKey + domain_name = settings.CONFIG.DOMAIN_NAME or 'jumpserver.org' app = cls.objects.create(username=name, name=name, email='%s@%s' % (name, domain_name), role='App', enable_otp=False, comment=comment, is_first_login=False, created_by='System') - AccessKey.object.create(user=app) + AccessKey.objects.create(user=app) return app @classmethod @@ -207,7 +208,7 @@ class User(AbstractUser): return super(User, self).delete() class Meta: - db_table = 'user' + ordering = ['username'] #: Use this method initial user @classmethod diff --git a/apps/users/models/utils.py b/apps/users/models/utils.py index 7dd8f7d25..8a9b6c370 100644 --- a/apps/users/models/utils.py +++ b/apps/users/models/utils.py @@ -7,10 +7,11 @@ from . import User, UserGroup def initial_model(): for cls in [User, UserGroup]: - cls.initial() + if getattr(cls, 'initial'): + cls.initial() def generate_fake(): for cls in [User, UserGroup]: - cls.generate_fake() - + if getattr(cls, 'generate_fake'): + cls.generate_fake()