From 5953e8e61f9b15f7bf3181788e731a3e9f07483f Mon Sep 17 00:00:00 2001 From: vapao Date: Thu, 3 Jun 2021 11:34:42 +0800 Subject: [PATCH] update --- spug_api/apps/account/models.py | 14 ++++---------- spug_api/apps/account/utils.py | 21 +++++++++++++++++++++ spug_api/apps/account/views.py | 7 +++---- spug_api/apps/exec/views.py | 3 ++- spug_api/apps/file/views.py | 9 +++++---- spug_api/apps/home/views.py | 5 +++-- spug_api/apps/host/group.py | 2 +- spug_api/apps/host/views.py | 8 ++++++-- spug_api/consumer/consumers.py | 3 ++- spug_web/src/libs/functools.js | 7 ------- spug_web/src/pages/login/index.js | 1 - spug_web/src/pages/schedule/Step2.js | 3 +-- spug_web/src/pages/system/role/HostPerm.js | 4 ++-- 13 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 spug_api/apps/account/utils.py diff --git a/spug_api/apps/account/models.py b/spug_api/apps/account/models.py index a0437d3..4e2608c 100644 --- a/spug_api/apps/account/models.py +++ b/spug_api/apps/account/models.py @@ -52,13 +52,8 @@ class User(models.Model, ModelMixin): return perms @property - def host_perms(self): - return json.loads(self.role.host_perms) if self.role and self.role.host_perms else [] - - def has_host_perm(self, host_id): - if isinstance(host_id, (list, set, tuple)): - return self.is_supper or set(host_id).issubset(set(self.host_perms)) - return self.is_supper or int(host_id) in self.host_perms + def group_perms(self): + return json.loads(self.role.group_perms) if self.role and self.role.group_perms else [] def has_perms(self, codes): # return self.is_supper or self.role in codes @@ -77,8 +72,7 @@ class Role(models.Model, ModelMixin): desc = models.CharField(max_length=255, null=True) page_perms = models.TextField(null=True) deploy_perms = models.TextField(null=True) - host_perms = models.TextField(null=True) - + group_perms = models.TextField(null=True) created_at = models.CharField(max_length=20, default=human_datetime) created_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+') @@ -86,7 +80,7 @@ class Role(models.Model, ModelMixin): tmp = super().to_dict(*args, **kwargs) tmp['page_perms'] = json.loads(self.page_perms) if self.page_perms else {} tmp['deploy_perms'] = json.loads(self.deploy_perms) if self.deploy_perms else {} - tmp['host_perms'] = json.loads(self.host_perms) if self.host_perms else [] + tmp['group_perms'] = json.loads(self.group_perms) if self.group_perms else [] tmp['used'] = self.user_set.count() return tmp diff --git a/spug_api/apps/account/utils.py b/spug_api/apps/account/utils.py new file mode 100644 index 0000000..a585693 --- /dev/null +++ b/spug_api/apps/account/utils.py @@ -0,0 +1,21 @@ +# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug +# Copyright: (c) +# Released under the AGPL-3.0 License. +from apps.host.models import Group + + +def get_host_perms(user): + ids = sub_ids = set(user.group_perms) + while sub_ids: + sub_ids = [x.id for x in Group.objects.filter(parent_id__in=sub_ids)] + ids.update(sub_ids) + return set(x.host_id for x in Group.hosts.through.objects.filter(group_id__in=ids)) + + +def has_host_perm(user, target): + if user.is_supper: + return True + host_ids = get_host_perms(user) + if isinstance(target, (list, set, tuple)): + return set(target).issubset(host_ids) + return int(target) in host_ids diff --git a/spug_api/apps/account/views.py b/spug_api/apps/account/views.py index a32fece..5b31934 100644 --- a/spug_api/apps/account/views.py +++ b/spug_api/apps/account/views.py @@ -100,7 +100,7 @@ class RoleView(View): Argument('id', type=int, help='参数错误'), Argument('page_perms', type=dict, required=False), Argument('deploy_perms', type=dict, required=False), - Argument('host_perms', type=list, required=False) + Argument('group_perms', type=list, required=False) ).parse(request.body) if error is None: role = Role.objects.filter(pk=form.pop('id')).first() @@ -110,8 +110,8 @@ class RoleView(View): role.page_perms = json.dumps(form.page_perms) if form.deploy_perms is not None: role.deploy_perms = json.dumps(form.deploy_perms) - if form.host_perms is not None: - role.host_perms = json.dumps(form.host_perms) + if form.group_perms is not None: + role.group_perms = json.dumps(form.group_perms) role.user_set.update(token_expired=0) role.save() return json_response(error=error) @@ -206,7 +206,6 @@ def handle_user_info(user, x_real_ip): 'nickname': user.nickname, 'is_supper': user.is_supper, 'has_real_ip': x_real_ip and ipaddress.ip_address(x_real_ip).is_global if verify_ip else True, - 'host_perms': [] if user.is_supper else user.host_perms, 'permissions': [] if user.is_supper else user.page_perms }) diff --git a/spug_api/apps/exec/views.py b/spug_api/apps/exec/views.py index 2bb455b..5553984 100644 --- a/spug_api/apps/exec/views.py +++ b/spug_api/apps/exec/views.py @@ -7,6 +7,7 @@ from django.conf import settings from libs import json_response, JsonParser, Argument, human_datetime from apps.exec.models import ExecTemplate from apps.host.models import Host +from apps.account.utils import has_host_perm import uuid import json @@ -50,7 +51,7 @@ def do_task(request): Argument('command', help='请输入执行命令内容') ).parse(request.body) if error is None: - if not request.user.has_host_perm(form.host_ids): + if not has_host_perm(request.user, form.host_ids): return json_response(error='无权访问主机,请联系管理员') token, rds = uuid.uuid4().hex, get_redis_connection() for host in Host.objects.filter(id__in=form.host_ids): diff --git a/spug_api/apps/file/views.py b/spug_api/apps/file/views.py index bd7c9e2..2f33b06 100644 --- a/spug_api/apps/file/views.py +++ b/spug_api/apps/file/views.py @@ -4,6 +4,7 @@ from django.views.generic import View from django_redis import get_redis_connection from apps.host.models import Host +from apps.account.utils import has_host_perm from apps.file.utils import FileResponseAfter, parse_sftp_attr from libs import json_response, JsonParser, Argument from functools import partial @@ -17,7 +18,7 @@ class FileView(View): Argument('path', help='参数错误') ).parse(request.GET) if error is None: - if not request.user.has_host_perm(form.id): + if not has_host_perm(request.user, form.id): return json_response(error='无权访问主机,请联系管理员') host = Host.objects.get(pk=form.id) if not host: @@ -35,7 +36,7 @@ class ObjectView(View): Argument('file', help='请输入文件路径') ).parse(request.GET) if error is None: - if not request.user.has_host_perm(form.id): + if not has_host_perm(request.user, form.id): return json_response(error='无权访问主机,请联系管理员') host = Host.objects.filter(pk=form.id).first() if not host: @@ -54,7 +55,7 @@ class ObjectView(View): Argument('path', help='参数错误'), ).parse(request.POST) if error is None: - if not request.user.has_host_perm(form.id): + if not has_host_perm(request.user, form.id): return json_response(error='无权访问主机,请联系管理员') file = request.FILES.get('file') if not file: @@ -74,7 +75,7 @@ class ObjectView(View): Argument('file', help='请输入文件路径') ).parse(request.GET) if error is None: - if not request.user.has_host_perm(form.id): + if not has_host_perm(request.user, form.id): return json_response(error='无权访问主机,请联系管理员') host = Host.objects.get(pk=form.id) if not host: diff --git a/spug_api/apps/home/views.py b/spug_api/apps/home/views.py index a26efff..bb6d806 100644 --- a/spug_api/apps/home/views.py +++ b/spug_api/apps/home/views.py @@ -8,6 +8,7 @@ from apps.schedule.models import Task from apps.monitor.models import Detection from apps.alarm.models import Alarm from apps.deploy.models import Deploy, DeployRequest +from apps.account.utils import get_host_perms from libs.utils import json_response, human_date, parse_time from libs.parser import JsonParser, Argument from datetime import datetime, timedelta @@ -19,9 +20,9 @@ def get_statistic(request): app = App.objects.count() host = Host.objects.count() else: - deploy_perms, host_perms = request.user.deploy_perms, request.user.host_perms + deploy_perms, host_perms = request.user.deploy_perms, get_host_perms(request.user) app = App.objects.filter(id__in=deploy_perms['apps']).count() - host = Host.objects.filter(id__in=host_perms).count() + host = len(host_perms) data = { 'app': app, 'host': host, diff --git a/spug_api/apps/host/group.py b/spug_api/apps/host/group.py index 90dfd65..5bf93ba 100644 --- a/spug_api/apps/host/group.py +++ b/spug_api/apps/host/group.py @@ -50,7 +50,7 @@ class GroupView(View): if request.user.is_supper: tree_data = list(data.values()) else: - tree_data, ids = [], request.user.host_perms + tree_data, ids = [], request.user.group_perms filter_by_perm(data.values(), tree_data, ids) merge_children(data2, '', tree_data) return json_response({'treeData': tree_data, 'groups': data2}) diff --git a/spug_api/apps/host/views.py b/spug_api/apps/host/views.py index b1fbb40..0f721ca 100644 --- a/spug_api/apps/host/views.py +++ b/spug_api/apps/host/views.py @@ -6,6 +6,7 @@ from django.db.models import F from django.http.response import HttpResponseBadRequest from libs import json_response, JsonParser, Argument from apps.setting.utils import AppSetting +from apps.account.utils import get_host_perms from apps.host.models import Host, Group from apps.app.models import Deploy from apps.schedule.models import Task @@ -18,8 +19,11 @@ from openpyxl import load_workbook class HostView(View): def get(self, request): - hosts = {x.id: x.to_view() for x in Host.objects.select_related('hostextend').all()} - for rel in Group.hosts.through.objects.all(): + hosts = Host.objects.select_related('hostextend') + if not request.user.is_supper: + hosts = hosts.filter(id__in=get_host_perms(request.user)) + hosts = {x.id: x.to_view() for x in hosts} + for rel in Group.hosts.through.objects.filter(host_id__in=hosts.keys()): hosts[rel.host_id]['group_ids'].append(rel.group_id) return json_response(list(hosts.values())) diff --git a/spug_api/consumer/consumers.py b/spug_api/consumer/consumers.py index 5ff518c..1dbc5fc 100644 --- a/spug_api/consumer/consumers.py +++ b/spug_api/consumer/consumers.py @@ -6,6 +6,7 @@ from django.conf import settings from django_redis import get_redis_connection from asgiref.sync import async_to_sync from apps.host.models import Host +from apps.account.utils import has_host_perm from threading import Thread import time import json @@ -109,7 +110,7 @@ class SSHConsumer(WebsocketConsumer): # print('Connection close') def connect(self): - if self.user.has_host_perm(self.id): + if has_host_perm(self.user, self.id): self.accept() self._init() else: diff --git a/spug_web/src/libs/functools.js b/spug_web/src/libs/functools.js index 67bbbab..51adf1b 100644 --- a/spug_web/src/libs/functools.js +++ b/spug_web/src/libs/functools.js @@ -6,7 +6,6 @@ let Permission = { isReady: false, isSuper: false, - hostPerms: [], permissions: [] }; @@ -16,7 +15,6 @@ export function updatePermissions() { X_TOKEN = localStorage.getItem('token'); Permission.isReady = true; Permission.isSuper = localStorage.getItem('is_supper') === 'true'; - Permission.hostPerms = JSON.parse(localStorage.getItem('host_perms') || '[]'); Permission.permissions = JSON.parse(localStorage.getItem('permissions') || '[]'); } @@ -32,11 +30,6 @@ export function hasPermission(strCode) { return false } -export function hasHostPermission(id) { - const {isSuper, hostPerms} = Permission; - return isSuper || hostPerms.includes(id) -} - export function includes(s, key) { key = key.toLowerCase(); if (s) { diff --git a/spug_web/src/pages/login/index.js b/spug_web/src/pages/login/index.js index ea4b20b..716d6bb 100644 --- a/spug_web/src/pages/login/index.js +++ b/spug_web/src/pages/login/index.js @@ -69,7 +69,6 @@ export default function () { localStorage.setItem('nickname', data['nickname']); localStorage.setItem('is_supper', data['is_supper']); localStorage.setItem('permissions', JSON.stringify(data['permissions'])); - localStorage.setItem('host_perms', JSON.stringify(data['host_perms'])); updatePermissions(); if (history.location.state && history.location.state['from']) { history.push(history.location.state['from']) diff --git a/spug_web/src/pages/schedule/Step2.js b/spug_web/src/pages/schedule/Step2.js index f3b9c37..623c823 100644 --- a/spug_web/src/pages/schedule/Step2.js +++ b/spug_web/src/pages/schedule/Step2.js @@ -7,7 +7,6 @@ import React from 'react'; import { observer } from 'mobx-react'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { Form, Select, Button } from 'antd'; -import { hasHostPermission } from 'libs'; import store from './store'; import hostStore from 'pages/host/store'; import styles from './index.module.css'; @@ -27,7 +26,7 @@ export default observer(function () { filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} onChange={v => store.editTarget(index, v)}> 本机 - {hostStore.records.filter(x => x.id === id || hasHostPermission(x.id)).map(item => ( + {hostStore.records.map(item => ( {`${item.name}(${item['hostname']}:${item['port']})`} diff --git a/spug_web/src/pages/system/role/HostPerm.js b/spug_web/src/pages/system/role/HostPerm.js index 456f388..54f73cd 100644 --- a/spug_web/src/pages/system/role/HostPerm.js +++ b/spug_web/src/pages/system/role/HostPerm.js @@ -14,7 +14,7 @@ import styles from './index.module.css'; export default observer(function () { const [loading, setLoading] = useState(false); - const [groups, setGroups] = useState([...store.record.host_perms]); + const [groups, setGroups] = useState([...store.record.group_perms]); useEffect(() => { if (hostStore.treeData.length === 0) { @@ -24,7 +24,7 @@ export default observer(function () { function handleSubmit() { setLoading(true); - http.patch('/api/account/role/', {id: store.record.id, host_perms: groups}) + http.patch('/api/account/role/', {id: store.record.id, group_perms: groups}) .then(res => { message.success('操作成功'); store.hostPermVisible = false;