pull/330/head
vapao 2021-06-03 11:34:42 +08:00
parent 8bb828a4cb
commit 5953e8e61f
13 changed files with 50 additions and 37 deletions

View File

@ -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

View File

@ -0,0 +1,21 @@
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
# Copyright: (c) <spug.dev@gmail.com>
# 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

View File

@ -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
})

View File

@ -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):

View File

@ -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:

View File

@ -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,

View File

@ -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})

View File

@ -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()))

View File

@ -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:

View File

@ -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) {

View File

@ -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'])

View File

@ -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)}>
<Select.Option value="local" disabled={store.targets.includes('local')}>本机</Select.Option>
{hostStore.records.filter(x => x.id === id || hasHostPermission(x.id)).map(item => (
{hostStore.records.map(item => (
<Select.Option key={item.id} value={item.id} disabled={store.targets.includes(item.id)}>
{`${item.name}(${item['hostname']}:${item['port']})`}
</Select.Option>

View File

@ -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;