mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
e0e14a2fe1
|
@ -5,8 +5,10 @@
|
|||
import logging
|
||||
import uuid
|
||||
from functools import reduce
|
||||
from collections import Iterable
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
|
@ -57,13 +59,17 @@ class NodesRelationMixin:
|
|||
return nodes
|
||||
|
||||
def get_all_nodes(self, flat=False):
|
||||
nodes = []
|
||||
from ..node import Node
|
||||
node_keys = set()
|
||||
for node in self.get_nodes():
|
||||
_nodes = node.get_ancestors(with_self=True)
|
||||
nodes.append(_nodes)
|
||||
ancestor_keys = node.get_ancestor_keys(with_self=True)
|
||||
node_keys.update(ancestor_keys)
|
||||
nodes = Node.objects.filter(key__in=node_keys).distinct()
|
||||
if flat:
|
||||
nodes = list(reduce(lambda x, y: set(x) | set(y), nodes))
|
||||
return nodes
|
||||
node_ids = set(nodes.values_list('id', flat=True))
|
||||
return node_ids
|
||||
else:
|
||||
return nodes
|
||||
|
||||
|
||||
class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
||||
|
@ -161,6 +167,14 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
|||
tree_node = TreeNode(**data)
|
||||
return tree_node
|
||||
|
||||
def filter_accounts(self, account_names=None):
|
||||
if account_names is None:
|
||||
return self.accounts.all()
|
||||
assert isinstance(account_names, Iterable), '`account_names` must be an iterable object'
|
||||
queries = Q(name__in=account_names) | Q(username__in=account_names)
|
||||
accounts = self.accounts.filter(queries)
|
||||
return accounts
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _("Asset")
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import uuid
|
||||
import time
|
||||
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.decorators import method_decorator
|
||||
from rest_framework.views import APIView, Response
|
||||
|
@ -20,6 +21,7 @@ from common.utils import get_logger, lazyproperty
|
|||
|
||||
from perms.hands import User, Asset
|
||||
from perms import serializers
|
||||
from perms.models import AssetPermission
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
@ -28,6 +30,8 @@ __all__ = [
|
|||
'ValidateUserAssetPermissionApi',
|
||||
'GetUserAssetPermissionActionsApi',
|
||||
'MyGrantedAssetSystemUsersApi',
|
||||
'UserGrantedAssetAccounts',
|
||||
'MyGrantedAssetAccounts',
|
||||
]
|
||||
|
||||
|
||||
|
@ -138,3 +142,37 @@ class MyGrantedAssetSystemUsersApi(UserGrantedAssetSystemUsersForAdminApi):
|
|||
def user(self):
|
||||
return self.request.user
|
||||
|
||||
|
||||
class UserGrantedAssetAccounts(ListAPIView):
|
||||
serializer_class = serializers.AccountsGrantedSerializer
|
||||
rbac_perms = {
|
||||
'list': 'perms.view_userassets'
|
||||
}
|
||||
|
||||
@lazyproperty
|
||||
def user(self):
|
||||
user_id = self.kwargs.get('pk')
|
||||
return User.objects.get(id=user_id)
|
||||
|
||||
@lazyproperty
|
||||
def asset(self):
|
||||
asset_id = self.kwargs.get('asset_id')
|
||||
kwargs = {'id': asset_id, 'is_active': True}
|
||||
asset = get_object_or_404(Asset, **kwargs)
|
||||
return asset
|
||||
|
||||
def get_queryset(self):
|
||||
# 获取用户-资产的授权规则
|
||||
assetperms = AssetPermission.filter_permissions(self.user, self.asset)
|
||||
account_names = AssetPermission.get_account_names(assetperms)
|
||||
accounts = self.asset.filter_accounts(account_names)
|
||||
# 构造默认包含的账号,如: @INPUT @USER
|
||||
return accounts
|
||||
|
||||
|
||||
class MyGrantedAssetAccounts(UserGrantedAssetAccounts):
|
||||
permission_classes = (IsValidUser,)
|
||||
|
||||
@lazyproperty
|
||||
def user(self):
|
||||
return self.request.user
|
||||
|
|
|
@ -19,7 +19,7 @@ from perms.utils.user_permission import UserGrantedNodesQueryUtils
|
|||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedNodesForAdminApi',
|
||||
'UserGrantedNodesApi',
|
||||
'MyGrantedNodesApi',
|
||||
'MyGrantedNodesAsTreeApi',
|
||||
'UserGrantedNodeChildrenForAdminApi',
|
||||
|
@ -118,11 +118,11 @@ class MyGrantedNodeChildrenAsTreeApi(AssetRoleUserMixin, UserGrantedNodeChildren
|
|||
return permissions
|
||||
|
||||
|
||||
class UserGrantedNodesForAdminApi(AssetRoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
|
||||
class UserGrantedNodesApi(AssetRoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
|
||||
pass
|
||||
|
||||
|
||||
class MyGrantedNodesApi(AssetRoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
|
||||
class MyGrantedNodesApi(AssetRoleUserMixin, UserGrantedNodesApi):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import uuid
|
||||
import logging
|
||||
from functools import reduce
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db import models
|
||||
from django.db.models import F, Q, TextChoices
|
||||
|
||||
from assets.models import Asset, Node, FamilyMixin
|
||||
from assets.models import Asset, Node, FamilyMixin, Account
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from orgs.mixins.models import OrgManager
|
||||
from common.utils import lazyproperty, date_expired_default
|
||||
from common.db.models import BaseCreateUpdateModel, BitOperationChoice, UnionQuerySet
|
||||
|
||||
|
||||
__all__ = [
|
||||
'AssetPermission', 'PermNode',
|
||||
'UserAssetGrantedTreeNodeRelation',
|
||||
|
@ -85,20 +85,27 @@ class AssetPermissionManager(OrgManager):
|
|||
class AssetPermission(OrgModelMixin):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"), related_name='%(class)ss')
|
||||
user_groups = models.ManyToManyField('users.UserGroup', blank=True, verbose_name=_("User group"), related_name='%(class)ss')
|
||||
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
|
||||
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
|
||||
users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"),
|
||||
related_name='%(class)ss')
|
||||
user_groups = models.ManyToManyField('users.UserGroup', blank=True,
|
||||
verbose_name=_("User group"), related_name='%(class)ss')
|
||||
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions',
|
||||
blank=True, verbose_name=_("Asset"))
|
||||
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True,
|
||||
verbose_name=_("Nodes"))
|
||||
# 只保存 @ALL (@INPUT @USER 默认包含,将来在全局设置中进行控制)
|
||||
# 特殊的账号描述
|
||||
# ['@ALL',]
|
||||
# 指定账号授权
|
||||
# ['web', 'root',]
|
||||
accounts = models.JSONField(default=list, verbose_name=_("Accounts"))
|
||||
actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_("Actions"))
|
||||
actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL,
|
||||
verbose_name=_("Actions"))
|
||||
is_active = models.BooleanField(default=True, verbose_name=_('Active'))
|
||||
date_start = models.DateTimeField(default=timezone.now, db_index=True, verbose_name=_("Date start"))
|
||||
date_expired = models.DateTimeField(default=date_expired_default, db_index=True, verbose_name=_('Date expired'))
|
||||
date_start = models.DateTimeField(default=timezone.now, db_index=True,
|
||||
verbose_name=_("Date start"))
|
||||
date_expired = models.DateTimeField(default=date_expired_default, db_index=True,
|
||||
verbose_name=_('Date expired'))
|
||||
created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created'))
|
||||
from_ticket = models.BooleanField(default=False, verbose_name=_('From ticket'))
|
||||
|
@ -106,6 +113,11 @@ class AssetPermission(OrgModelMixin):
|
|||
|
||||
objects = AssetPermissionManager.from_queryset(AssetPermissionQuerySet)()
|
||||
|
||||
class SpecialAccount(models.TextChoices):
|
||||
ALL = '@ALL', 'All'
|
||||
INPUT = '@INPUT', 'Input'
|
||||
USER = '@USER', 'User'
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _("Asset permission")
|
||||
|
@ -174,14 +186,17 @@ class AssetPermission(OrgModelMixin):
|
|||
models.Prefetch('assets', queryset=Asset.objects.all().only('id')),
|
||||
).order_by()
|
||||
|
||||
def get_all_assets(self):
|
||||
def get_all_assets(self, flat=False):
|
||||
from assets.models import Node
|
||||
nodes_keys = self.nodes.all().values_list('key', flat=True)
|
||||
asset_ids = set(self.assets.all().values_list('id', flat=True))
|
||||
nodes_asset_ids = Node.get_nodes_all_asset_ids_by_keys(nodes_keys)
|
||||
asset_ids.update(nodes_asset_ids)
|
||||
assets = Asset.objects.filter(id__in=asset_ids)
|
||||
return assets
|
||||
if flat:
|
||||
return asset_ids
|
||||
else:
|
||||
assets = Asset.objects.filter(id__in=asset_ids)
|
||||
return assets
|
||||
|
||||
def users_display(self):
|
||||
names = [user.username for user in self.users.all()]
|
||||
|
@ -199,6 +214,94 @@ class AssetPermission(OrgModelMixin):
|
|||
names = [node.full_value for node in self.nodes.all()]
|
||||
return names
|
||||
|
||||
def get_asset_accounts(self):
|
||||
asset_ids = self.get_all_assets(flat=True)
|
||||
queries = Q(asset_id__in=asset_ids) \
|
||||
& (Q(username__in=self.accounts) | Q(name__in=self.accounts))
|
||||
accounts = Account.objects.filter(queries)
|
||||
return accounts
|
||||
|
||||
@classmethod
|
||||
def get_account_names(cls, perms):
|
||||
account_names = set()
|
||||
for perm in perms:
|
||||
perm: cls
|
||||
if not isinstance(perm.accounts, list):
|
||||
continue
|
||||
account_names.update(perm.accounts)
|
||||
return account_names
|
||||
|
||||
@classmethod
|
||||
def filter_permissions(cls, user=None, asset=None, account=None):
|
||||
""" 获取同时包含 用户-资产-账号 的授权规则 """
|
||||
assetperm_ids = []
|
||||
if user:
|
||||
user_assetperm_ids = cls.filter_permissions_by_user(user, flat=True)
|
||||
assetperm_ids.append(user_assetperm_ids)
|
||||
if asset:
|
||||
asset_assetperm_ids = cls.filter_permissions_by_asset(asset, flat=True)
|
||||
assetperm_ids.append(asset_assetperm_ids)
|
||||
if account:
|
||||
account_assetperm_ids = cls.filter_permissions_by_account(account, flat=True)
|
||||
assetperm_ids.append(account_assetperm_ids)
|
||||
# & 是同时满足,比如有用户,但是用户的规则是空,那么返回也应该是空
|
||||
assetperm_ids = list(reduce(lambda x, y: set(x) & set(y), assetperm_ids))
|
||||
assetperms = cls.objects.filter(id__in=assetperm_ids).valid().order_by('-date_expired')
|
||||
return assetperms
|
||||
|
||||
@classmethod
|
||||
def filter_permissions_by_user(cls, user, with_group=True, flat=False):
|
||||
assetperm_ids = set()
|
||||
user_assetperm_ids = AssetPermission.users.through.objects \
|
||||
.filter(user_id=user.id) \
|
||||
.values_list('assetpermission_id', flat=True) \
|
||||
.distinct()
|
||||
assetperm_ids.update(user_assetperm_ids)
|
||||
|
||||
if with_group:
|
||||
usergroup_ids = user.get_groups(flat=True)
|
||||
usergroups_assetperm_id = AssetPermission.user_groups.through.objects \
|
||||
.filter(usergroup_id__in=usergroup_ids) \
|
||||
.values_list('assetpermission_id', flat=True) \
|
||||
.distinct()
|
||||
assetperm_ids.update(usergroups_assetperm_id)
|
||||
|
||||
if flat:
|
||||
return assetperm_ids
|
||||
else:
|
||||
assetperms = cls.objects.filter(id__in=assetperm_ids).valid()
|
||||
return assetperms
|
||||
|
||||
@classmethod
|
||||
def filter_permissions_by_asset(cls, asset, with_node=True, flat=False):
|
||||
assetperm_ids = set()
|
||||
asset_assetperm_ids = AssetPermission.assets.through.objects \
|
||||
.filter(asset_id=asset.id) \
|
||||
.values_list('assetpermission_id', flat=True)
|
||||
assetperm_ids.update(asset_assetperm_ids)
|
||||
|
||||
if with_node:
|
||||
node_ids = asset.get_all_nodes(flat=True)
|
||||
node_assetperm_ids = AssetPermission.nodes.through.objects \
|
||||
.filter(node_id__in=node_ids) \
|
||||
.values_list('assetpermission_id', flat=True)
|
||||
assetperm_ids.update(node_assetperm_ids)
|
||||
|
||||
if flat:
|
||||
return assetperm_ids
|
||||
else:
|
||||
assetperms = cls.objects.filter(id__in=assetperm_ids).valid()
|
||||
return assetperms
|
||||
|
||||
@classmethod
|
||||
def filter_permissions_by_account(cls, account, flat=False):
|
||||
assetperms = cls.objects.filter(accounts__contains=account).valid()
|
||||
if flat:
|
||||
assetperm_ids = assetperms.values_list('id', flat=True)
|
||||
return assetperm_ids
|
||||
else:
|
||||
return assetperms
|
||||
|
||||
|
||||
class UserAssetGrantedTreeNodeRelation(OrgModelMixin, FamilyMixin, BaseCreateUpdateModel):
|
||||
class NodeFrom(TextChoices):
|
||||
|
@ -210,7 +313,8 @@ class UserAssetGrantedTreeNodeRelation(OrgModelMixin, FamilyMixin, BaseCreateUpd
|
|||
node = models.ForeignKey('assets.Node', default=None, on_delete=models.CASCADE,
|
||||
db_constraint=False, null=False, related_name='granted_node_rels')
|
||||
node_key = models.CharField(max_length=64, verbose_name=_("Key"), db_index=True)
|
||||
node_parent_key = models.CharField(max_length=64, default='', verbose_name=_('Parent key'), db_index=True)
|
||||
node_parent_key = models.CharField(max_length=64, default='', verbose_name=_('Parent key'),
|
||||
db_index=True)
|
||||
node_from = models.CharField(choices=NodeFrom.choices, max_length=16, db_index=True)
|
||||
node_assets_amount = models.IntegerField(default=0)
|
||||
|
||||
|
@ -297,4 +401,3 @@ class PermedAsset(Asset):
|
|||
('view_userassets', _('Can view user assets')),
|
||||
('view_usergroupassets', _('Can view usergroup assets')),
|
||||
]
|
||||
|
||||
|
|
|
@ -4,20 +4,19 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from assets.models import Node, Asset, Platform
|
||||
from assets.models import Node, Asset, Platform, Account
|
||||
from perms.serializers.permission import ActionsField
|
||||
|
||||
__all__ = [
|
||||
'NodeGrantedSerializer',
|
||||
'AssetGrantedSerializer',
|
||||
'ActionsSerializer',
|
||||
'AccountsGrantedSerializer'
|
||||
]
|
||||
|
||||
|
||||
class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
被授权资产的数据结构
|
||||
"""
|
||||
""" 被授权资产的数据结构 """
|
||||
platform = serializers.SlugRelatedField(
|
||||
slug_field='name', queryset=Platform.objects.all(), label=_("Platform")
|
||||
)
|
||||
|
@ -44,3 +43,14 @@ class NodeGrantedSerializer(serializers.ModelSerializer):
|
|||
class ActionsSerializer(serializers.Serializer):
|
||||
actions = ActionsField(read_only=True)
|
||||
|
||||
|
||||
class AccountsGrantedSerializer(serializers.ModelSerializer):
|
||||
""" 授权的账号序列类 """
|
||||
|
||||
# Todo: 添加前端登录逻辑中需要的一些字段,比如:是否需要手动输入密码
|
||||
# need_manual = serializers.BooleanField(label=_('Need manual input'))
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['id', 'name', 'username']
|
||||
read_only_fields = fields
|
||||
|
|
|
@ -5,7 +5,6 @@ from rest_framework_bulk.routes import BulkRouter
|
|||
|
||||
from .. import api
|
||||
|
||||
# v3 Done
|
||||
router = BulkRouter()
|
||||
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
|
||||
router.register('asset-permissions-users-relations', api.AssetPermissionUserRelationViewSet, 'asset-permissions-users-relation')
|
||||
|
@ -14,42 +13,31 @@ router.register('asset-permissions-assets-relations', api.AssetPermissionAssetRe
|
|||
router.register('asset-permissions-nodes-relations', api.AssetPermissionNodeRelationViewSet, 'asset-permissions-nodes-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
# 统一说明:
|
||||
# `<uuid:pk>`: `User.pk`
|
||||
# 直接授权:在 `AssetPermission` 中关联的对象
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 以 serializer 格式返回
|
||||
path('<uuid:pk>/assets/', api.UserAllGrantedAssetsApi.as_view(), name='user-assets'),
|
||||
path('assets/', api.MyAllGrantedAssetsApi.as_view(), name='my-assets'),
|
||||
|
||||
# Tree Node 的数据格式返回
|
||||
path('<uuid:pk>/assets/tree/', api.UserDirectGrantedAssetsAsTreeApi.as_view(), name='user-assets-as-tree'),
|
||||
path('assets/tree/', api.MyAllAssetsAsTreeApi.as_view(), name='my-assets-as-tree'),
|
||||
path('ungroup/assets/tree/', api.MyUngroupAssetsAsTreeApi.as_view(), name='my-ungroup-assets-as-tree'),
|
||||
# ^--------------------------------------------------------^
|
||||
|
||||
# 获取用户所有`直接授权的节点`与`直接授权资产`关联的节点
|
||||
# 以 serializer 格式返回
|
||||
path('<uuid:pk>/nodes/', api.UserGrantedNodesForAdminApi.as_view(), name='user-nodes'),
|
||||
path('<uuid:pk>/nodes/', api.UserGrantedNodesApi.as_view(), name='user-nodes'),
|
||||
path('nodes/', api.MyGrantedNodesApi.as_view(), name='my-nodes'),
|
||||
|
||||
# 以 Tree Node 的数据格式返回
|
||||
path('<uuid:pk>/nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='user-nodes-as-tree'),
|
||||
path('nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='my-nodes-as-tree'),
|
||||
# ^--------------------------------------------------------^
|
||||
|
||||
# 一层一层的获取用户授权的节点,
|
||||
# 以 Serializer 的数据格式返回
|
||||
path('<uuid:pk>/nodes/children/', api.UserGrantedNodeChildrenForAdminApi.as_view(), name='user-nodes-children'),
|
||||
path('nodes/children/', api.MyGrantedNodeChildrenApi.as_view(), name='my-nodes-children'),
|
||||
|
||||
# 以 Tree Node 的数据格式返回
|
||||
path('<uuid:pk>/nodes/children/tree/', api.UserGrantedNodeChildrenAsTreeForAdminApi.as_view(), name='user-nodes-children-as-tree'),
|
||||
# 部分调用位置
|
||||
# - 普通用户 -> 我的资产 -> 展开节点 时调用
|
||||
path('nodes/children/tree/', api.MyGrantedNodeChildrenAsTreeApi.as_view(), name='my-nodes-children-as-tree'),
|
||||
# ^--------------------------------------------------------^
|
||||
|
||||
# 此接口会返回整棵树
|
||||
# 普通用户 -> 命令执行 -> 左侧树
|
||||
|
@ -75,6 +63,11 @@ user_permission_urlpatterns = [
|
|||
# Asset System users
|
||||
path('<uuid:pk>/assets/<uuid:asset_id>/system-users/', api.UserGrantedAssetSystemUsersForAdminApi.as_view(), name='user-asset-system-users'),
|
||||
path('assets/<uuid:asset_id>/system-users/', api.MyGrantedAssetSystemUsersApi.as_view(), name='my-asset-system-users'),
|
||||
|
||||
# Todo: 增加
|
||||
# 获取所有和资产相关联的账号列表
|
||||
path('<uuid:pk>/assets/<uuid:asset_id>/accounts/', api.UserGrantedAssetAccounts.as_view(), name='user-asset-accounts'),
|
||||
path('assets/<uuid:asset_id>/accounts/', api.MyGrantedAssetAccounts.as_view(), name='my-asset-accounts')
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
|
|
|
@ -918,6 +918,21 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
|
|||
return True
|
||||
return False
|
||||
|
||||
def get_groups(self, flat=False):
|
||||
from users.models import UserGroup
|
||||
usergroup_ids = self.groups.through.objects\
|
||||
.filter(user_id=self.id)\
|
||||
.distinct()\
|
||||
.values_list('usergroup_id', flat=True)
|
||||
usergroups = UserGroup.objects.filter(id__in=usergroup_ids)
|
||||
if flat:
|
||||
usergroup_ids = usergroups.values_list('id', flat=True)
|
||||
return usergroup_ids
|
||||
else:
|
||||
return usergroups
|
||||
|
||||
|
||||
|
||||
|
||||
class UserPasswordHistory(models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
|
||||
# >>> Django 环境配置
|
||||
import django
|
||||
import os
|
||||
import sys
|
||||
|
||||
if os.path.exists('../apps'):
|
||||
sys.path.insert(0, '../apps')
|
||||
elif os.path.exists('./apps'):
|
||||
sys.path.insert(0, './apps')
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
APPS_DIR = os.path.join(BASE_DIR, 'apps')
|
||||
sys.path.insert(0, APPS_DIR)
|
||||
|
||||
os.environ.setdefault('PYTHONOPTIMIZE', '1')
|
||||
if os.getuid() == 0:
|
||||
os.environ.setdefault('C_FORCE_ROOT', '1')
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings")
|
||||
django.setup()
|
||||
|
||||
# <<<
|
||||
|
||||
|
||||
class Generator(object):
|
||||
|
||||
def generate(self):
|
||||
pass
|
||||
|
||||
def generate_assets(self):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
Loading…
Reference in New Issue