mirror of https://github.com/jumpserver/jumpserver
commit
714b6b1233
|
@ -15,7 +15,7 @@ class TempTokenViewSet(JMSModelViewSet):
|
|||
|
||||
def get_queryset(self):
|
||||
username = self.request.user.username
|
||||
return TempToken.objects.filter(username=username)
|
||||
return TempToken.objects.filter(username=username).order_by('-date_created')
|
||||
|
||||
@action(methods=['PATCH'], detail=True, url_path='expire')
|
||||
def expire(self, *args, **kwargs):
|
||||
|
@ -24,4 +24,3 @@ class TempTokenViewSet(JMSModelViewSet):
|
|||
instance.save()
|
||||
serializer = self.get_serializer(instance)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
|||
('secret', models.CharField(max_length=64, verbose_name='Secret')),
|
||||
('verified', models.BooleanField(default=False, verbose_name='Verified')),
|
||||
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
|
||||
('date_expired', models.DateTimeField(verbose_name='Date verified')),
|
||||
('date_expired', models.DateTimeField(verbose_name='Date expired')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Temporary token',
|
||||
|
|
|
@ -4,6 +4,7 @@ from rest_framework.exceptions import PermissionDenied
|
|||
from rest_framework.decorators import action
|
||||
|
||||
from common.drf.api import JMSModelViewSet
|
||||
from ..filters import RoleFilter
|
||||
from ..serializers import RoleSerializer, RoleUserSerializer
|
||||
from ..models import Role, SystemRole, OrgRole
|
||||
from .permission import PermissionViewSet
|
||||
|
@ -20,8 +21,8 @@ class RoleViewSet(JMSModelViewSet):
|
|||
'default': RoleSerializer,
|
||||
'users': RoleUserSerializer,
|
||||
}
|
||||
filterset_fields = ['name', 'scope', 'builtin']
|
||||
search_fields = filterset_fields
|
||||
filterset_class = RoleFilter
|
||||
search_fields = ('name', 'scope', 'builtin')
|
||||
rbac_perms = {
|
||||
'users': 'rbac.view_rolebinding'
|
||||
}
|
||||
|
|
|
@ -2,6 +2,13 @@ from django.utils.translation import ugettext_noop
|
|||
|
||||
from .const import Scope, system_exclude_permissions, org_exclude_permissions
|
||||
|
||||
system_user_perms = (
|
||||
('authentication', 'connectiontoken', 'add', 'connectiontoken'),
|
||||
('authentication', 'temptoken', 'add', 'temptoken'),
|
||||
('tickets', 'ticket', 'view', 'ticket'),
|
||||
('orgs', 'organization', 'view', 'rootorg'),
|
||||
)
|
||||
|
||||
# Todo: 获取应该区分 系统用户,和组织用户的权限
|
||||
# 工作台也区分组织后再考虑
|
||||
user_perms = (
|
||||
|
@ -15,10 +22,6 @@ user_perms = (
|
|||
('assets', 'node', 'match', 'node'),
|
||||
('applications', 'application', 'match', 'application'),
|
||||
('ops', 'commandexecution', 'add', 'commandexecution'),
|
||||
('authentication', 'connectiontoken', 'add', 'connectiontoken'),
|
||||
('authentication', 'temptoken', 'add', 'temptoken'),
|
||||
('tickets', 'ticket', 'view', 'ticket'),
|
||||
('orgs', 'organization', 'view', 'rootorg'),
|
||||
)
|
||||
|
||||
auditor_perms = user_perms + (
|
||||
|
@ -104,7 +107,7 @@ class BuiltinRole:
|
|||
'4', ugettext_noop('SystemComponent'), Scope.system, app_exclude_perms, 'exclude'
|
||||
)
|
||||
system_user = PredefineRole(
|
||||
'3', ugettext_noop('User'), Scope.system, user_perms
|
||||
'3', ugettext_noop('User'), Scope.system, system_user_perms
|
||||
)
|
||||
org_admin = PredefineRole(
|
||||
'5', ugettext_noop('OrgAdmin'), Scope.org, []
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
from django_filters import rest_framework as filters
|
||||
|
||||
from common.drf.filters import BaseFilterSet
|
||||
from rbac.models import Role
|
||||
|
||||
|
||||
class RoleFilter(BaseFilterSet):
|
||||
name = filters.CharFilter(method='filter_name')
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ('name', 'scope', 'builtin')
|
||||
|
||||
@staticmethod
|
||||
def filter_name(queryset, name, value):
|
||||
builtin_ids = []
|
||||
for role in queryset.filter(builtin=True):
|
||||
if value in role.display_name:
|
||||
builtin_ids.append(role.id)
|
||||
if builtin_ids:
|
||||
builtin_qs = queryset.model.objects.filter(id__in=builtin_ids)
|
||||
else:
|
||||
builtin_qs = queryset.model.objects.none()
|
||||
queryset = queryset.filter(name__icontains=value)
|
||||
return queryset | builtin_qs
|
|
@ -90,4 +90,3 @@ class Permission(DjangoPermission):
|
|||
permissions = cls.objects.all()
|
||||
permissions = cls.clean_permissions(permissions, scope=scope)
|
||||
return permissions
|
||||
|
||||
|
|
|
@ -121,6 +121,20 @@ class Role(JMSModel):
|
|||
def is_org(self):
|
||||
return self.scope == const.Scope.org
|
||||
|
||||
@classmethod
|
||||
def get_roles_by_perm(cls, perm):
|
||||
app_label, codename = perm.split('.')
|
||||
p = Permission.objects.filter(
|
||||
codename=codename,
|
||||
content_type__app_label=app_label
|
||||
).first()
|
||||
if not p:
|
||||
return p.roles.none()
|
||||
role_ids = list(p.roles.all().values_list('id', flat=True))
|
||||
admin_ids = [BuiltinRole.system_admin.id, BuiltinRole.org_admin.id]
|
||||
role_ids += admin_ids
|
||||
return cls.objects.filter(id__in=role_ids)
|
||||
|
||||
|
||||
class SystemRole(Role):
|
||||
objects = SystemRoleManager()
|
||||
|
|
|
@ -100,6 +100,28 @@ class RoleBinding(JMSModel):
|
|||
def is_scope_org(self):
|
||||
return self.scope == Scope.org
|
||||
|
||||
@classmethod
|
||||
def get_user_has_the_perm_orgs(cls, perm, user):
|
||||
from orgs.models import Organization
|
||||
|
||||
roles = Role.get_roles_by_perm(perm)
|
||||
bindings = list(cls.objects.root_all().filter(role__in=roles, user=user))
|
||||
system_bindings = [b for b in bindings if b.scope == Role.Scope.system.value]
|
||||
|
||||
if perm == 'rbac.view_workbench':
|
||||
all_orgs = user.orgs.all()
|
||||
else:
|
||||
all_orgs = Organization.objects.all()
|
||||
|
||||
if system_bindings:
|
||||
orgs = all_orgs
|
||||
else:
|
||||
org_ids = [b.org.id for b in bindings if b.org]
|
||||
orgs = all_orgs.filter(id__in=org_ids)
|
||||
if orgs and user.has_perm('orgs.view_rootorg'):
|
||||
orgs = [Organization.root(), *list(orgs)]
|
||||
return orgs
|
||||
|
||||
|
||||
class OrgRoleBindingManager(RoleBindingManager):
|
||||
def get_queryset(self):
|
||||
|
|
|
@ -59,10 +59,15 @@ class CommandStore(object):
|
|||
data = self.es.indices.get_mapping(self.index)
|
||||
except NotFoundError:
|
||||
return False
|
||||
|
||||
info = self.es.info()
|
||||
version = info['version']['number'].split('.')[0]
|
||||
try:
|
||||
# 检测索引是不是新的类型
|
||||
properties = data[self.index]['mappings']['properties']
|
||||
if version == '6':
|
||||
# 检测索引是不是新的类型 es6
|
||||
properties = data[self.index]['mappings']['data']['properties']
|
||||
else:
|
||||
# 检测索引是不是新的类型 es7 default index type: _doc
|
||||
properties = data[self.index]['mappings']['properties']
|
||||
if properties['session']['type'] == 'keyword' \
|
||||
and properties['org_id']['type'] == 'keyword':
|
||||
return True
|
||||
|
@ -75,27 +80,30 @@ class CommandStore(object):
|
|||
self._ensure_index_exists()
|
||||
|
||||
def _ensure_index_exists(self):
|
||||
mappings = {
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"session": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"org_id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
properties = {
|
||||
"session": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"org_id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
info = self.es.info()
|
||||
version = info['version']['number'].split('.')[0]
|
||||
if version == '6':
|
||||
mappings = {'mappings': {'data': {'properties': properties}}}
|
||||
else:
|
||||
mappings = {'mappings': {'properties': properties}}
|
||||
|
||||
try:
|
||||
self.es.indices.create(self.index, body=mappings)
|
||||
return
|
||||
except RequestError as e:
|
||||
logger.exception(e)
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ def migrate_endpoints(apps, schema_editor):
|
|||
'http_port': 0,
|
||||
'created_by': 'System'
|
||||
}
|
||||
default_endpoint = Endpoint.objects.create(**default_data)
|
||||
Endpoint.objects.create(**default_data)
|
||||
|
||||
if not settings.XRDP_ENABLED:
|
||||
return
|
||||
|
@ -81,8 +81,8 @@ class Migration(migrations.Migration):
|
|||
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
|
||||
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
|
||||
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128, unique=True, blank=True, verbose_name='Name')),
|
||||
('host', models.CharField(max_length=256, verbose_name='Host')),
|
||||
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
|
||||
('host', models.CharField(max_length=256, verbose_name='Host', blank=True)),
|
||||
('https_port', common.fields.model.PortField(default=443, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTPS Port')),
|
||||
('http_port', common.fields.model.PortField(default=80, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTP Port')),
|
||||
('ssh_port', common.fields.model.PortField(default=2222, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='SSH Port')),
|
||||
|
|
|
@ -863,23 +863,20 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
|
|||
return None
|
||||
return self.SOURCE_BACKEND_MAPPING.get(self.source, [])
|
||||
|
||||
@property
|
||||
def all_orgs(self):
|
||||
from rbac.builtin import BuiltinRole
|
||||
has_system_role = self.system_roles.all() \
|
||||
.exclude(name=BuiltinRole.system_user.name) \
|
||||
.exists()
|
||||
if has_system_role:
|
||||
orgs = list(Organization.objects.all())
|
||||
else:
|
||||
orgs = list(self.orgs.distinct())
|
||||
if self.has_perm('orgs.view_rootorg'):
|
||||
orgs = [Organization.root()] + orgs
|
||||
return orgs
|
||||
@lazyproperty
|
||||
def console_orgs(self):
|
||||
from rbac.models import RoleBinding
|
||||
return RoleBinding.get_user_has_the_perm_orgs('rbac.view_console', self)
|
||||
|
||||
@property
|
||||
def my_orgs(self):
|
||||
return list(self.orgs.distinct())
|
||||
@lazyproperty
|
||||
def audit_orgs(self):
|
||||
from rbac.models import RoleBinding
|
||||
return RoleBinding.get_user_has_the_perm_orgs('rbac.view_audit', self)
|
||||
|
||||
@lazyproperty
|
||||
def workbench_orgs(self):
|
||||
from rbac.models import RoleBinding
|
||||
return RoleBinding.get_user_has_the_perm_orgs('rbac.view_workbench', self)
|
||||
|
||||
class Meta:
|
||||
ordering = ['username']
|
||||
|
|
|
@ -121,14 +121,16 @@ class UserProfileSerializer(UserSerializer):
|
|||
mfa_level = serializers.ChoiceField(choices=MFA_LEVEL_CHOICES, label=_('MFA'), required=False)
|
||||
guide_url = serializers.SerializerMethodField()
|
||||
receive_backends = serializers.ListField(child=serializers.CharField(), read_only=True)
|
||||
orgs = UserOrgSerializer(many=True, read_only=True, source='all_orgs')
|
||||
myorgs = UserOrgSerializer(many=True, read_only=True, source='my_orgs')
|
||||
console_orgs = UserOrgSerializer(many=True, read_only=True)
|
||||
audit_orgs = UserOrgSerializer(many=True, read_only=True)
|
||||
workbench_orgs = UserOrgSerializer(many=True, read_only=True)
|
||||
perms = serializers.ListField(label=_("Perms"), read_only=True)
|
||||
|
||||
class Meta(UserSerializer.Meta):
|
||||
read_only_fields = [
|
||||
'date_joined', 'last_login', 'created_by', 'source',
|
||||
'receive_backends', 'orgs', 'myorgs', 'perms',
|
||||
'console_orgs', 'audit_orgs', 'workbench_orgs',
|
||||
'receive_backends', 'perms',
|
||||
]
|
||||
fields = UserSerializer.Meta.fields + [
|
||||
'public_key_comment', 'public_key_hash_md5', 'guide_url',
|
||||
|
|
Loading…
Reference in New Issue