mirror of https://github.com/openspug/spug
update
parent
8bb828a4cb
commit
5953e8e61f
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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()))
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue