U 安全性改进

pull/410/head
vapao 2021-11-24 18:44:08 +08:00
parent 282f785928
commit 2b33df0765
23 changed files with 158 additions and 140 deletions

View File

@ -3,11 +3,12 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from django.db.models import F from django.db.models import F
from libs import json_response from libs import json_response, auth
from apps.account.models import History from apps.account.models import History
class HistoryView(View): class HistoryView(View):
@auth('dashboard.dashboard.view')
def get(self, request): def get(self, request):
histories = [] histories = []
for item in History.objects.annotate(nickname=F('user__nickname')): for item in History.objects.annotate(nickname=F('user__nickname')):

View File

@ -2,6 +2,7 @@
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.db import models from django.db import models
from django.core.cache import cache
from libs import ModelMixin, human_datetime from libs import ModelMixin, human_datetime
from django.contrib.auth.hashers import make_password, check_password from django.contrib.auth.hashers import make_password, check_password
import json import json
@ -33,16 +34,25 @@ class User(models.Model, ModelMixin):
def verify_password(self, plain_password: str) -> bool: def verify_password(self, plain_password: str) -> bool:
return check_password(plain_password, self.password_hash) return check_password(plain_password, self.password_hash)
def get_perms_cache(self):
return cache.get(f'perms_{self.id}', set())
def set_perms_cache(self, value=None):
cache.set(f'perms_{self.id}', value or set())
@property @property
def page_perms(self): def page_perms(self):
data = set() data = self.get_perms_cache()
if data:
return data
for item in self.roles.all(): for item in self.roles.all():
if item.page_perms: if item.page_perms:
perms = json.loads(item.page_perms) perms = json.loads(item.page_perms)
for m, v in perms.items(): for m, v in perms.items():
for p, d in v.items(): for p, d in v.items():
data.update(f'{m}.{p}.{x}' for x in d) data.update(f'{m}.{p}.{x}' for x in d)
return list(data) self.set_perms_cache(data)
return data
@property @property
def deploy_perms(self): def deploy_perms(self):
@ -63,8 +73,9 @@ class User(models.Model, ModelMixin):
return list(data) return list(data)
def has_perms(self, codes): def has_perms(self, codes):
# return self.is_supper or self.role in codes if self.is_supper:
return self.is_supper return True
return self.page_perms.intersection(codes)
def __repr__(self): def __repr__(self):
return '<User %r>' % self.username return '<User %r>' % self.username
@ -99,6 +110,10 @@ class Role(models.Model, ModelMixin):
self.deploy_perms = json.dumps(perms) self.deploy_perms = json.dumps(perms)
self.save() self.save()
def clear_perms_cache(self):
for item in self.user_set.all():
item.set_perms_cache()
def __repr__(self): def __repr__(self):
return '<Role name=%r>' % self.name return '<Role name=%r>' % self.name

View File

@ -2,7 +2,7 @@
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.core.cache import cache from django.core.cache import cache
from django.views.generic import View from libs.mixins import AdminView, View
from libs import JsonParser, Argument, human_datetime, json_response from libs import JsonParser, Argument, human_datetime, json_response
from libs.utils import get_request_real_ip, generate_random_str from libs.utils import get_request_real_ip, generate_random_str
from libs.spug import send_login_wx_code from libs.spug import send_login_wx_code
@ -15,7 +15,7 @@ import uuid
import json import json
class UserView(View): class UserView(AdminView):
def get(self, request): def get(self, request):
users = [] users = []
for u in User.objects.filter(deleted_by_id__isnull=True): for u in User.objects.filter(deleted_by_id__isnull=True):
@ -50,6 +50,7 @@ class UserView(View):
**form **form
) )
user.roles.set(role_ids) user.roles.set(role_ids)
user.set_perms_cache()
return json_response(error=error) return json_response(error=error)
def patch(self, request): def patch(self, request):
@ -88,7 +89,7 @@ class UserView(View):
return json_response(error=error) return json_response(error=error)
class RoleView(View): class RoleView(AdminView):
def get(self, request): def get(self, request):
roles = Role.objects.all() roles = Role.objects.all()
return json_response(roles) return json_response(roles)
@ -119,6 +120,7 @@ class RoleView(View):
return json_response(error='未找到指定角色') return json_response(error='未找到指定角色')
if form.page_perms is not None: if form.page_perms is not None:
role.page_perms = json.dumps(form.page_perms) role.page_perms = json.dumps(form.page_perms)
role.clear_perms_cache()
if form.deploy_perms is not None: if form.deploy_perms is not None:
role.deploy_perms = json.dumps(form.deploy_perms) role.deploy_perms = json.dumps(form.deploy_perms)
if form.group_perms is not None: if form.group_perms is not None:
@ -240,7 +242,7 @@ def handle_user_info(request, user, captcha):
'nickname': user.nickname, 'nickname': user.nickname,
'is_supper': user.is_supper, '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, 'has_real_ip': x_real_ip and ipaddress.ip_address(x_real_ip).is_global if verify_ip else True,
'permissions': [] if user.is_supper else user.page_perms 'permissions': [] if user.is_supper else list(user.page_perms)
}) })

View File

@ -2,23 +2,26 @@
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument, auth
from apps.alarm.models import Alarm, Group, Contact from apps.alarm.models import Alarm, Group, Contact
from apps.monitor.models import Detection from apps.monitor.models import Detection
import json import json
class AlarmView(View): class AlarmView(View):
@auth('alarm.alarm.view')
def get(self, request): def get(self, request):
alarms = Alarm.objects.all() alarms = Alarm.objects.all()
return json_response(alarms) return json_response(alarms)
class GroupView(View): class GroupView(View):
@auth('alarm.group.view|monitor.monitor.add|monitor.monitor.edit|alarm.alarm.view')
def get(self, request): def get(self, request):
groups = Group.objects.all() groups = Group.objects.all()
return json_response(groups) return json_response(groups)
@auth('alarm.group.add|alarm.group.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -35,6 +38,7 @@ class GroupView(View):
Group.objects.create(**form) Group.objects.create(**form)
return json_response(error=error) return json_response(error=error)
@auth('alarm.group.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -48,10 +52,12 @@ class GroupView(View):
class ContactView(View): class ContactView(View):
@auth('alarm.contact.view|alarm.group.view')
def get(self, request): def get(self, request):
contacts = Contact.objects.all() contacts = Contact.objects.all()
return json_response(contacts) return json_response(contacts)
@auth('alarm.contact.add|alarm.contact.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -70,6 +76,7 @@ class ContactView(View):
Contact.objects.create(**form) Contact.objects.create(**form)
return json_response(error=error) return json_response(error=error)
@auth('alarm.contact.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')

View File

@ -3,7 +3,7 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from django.db.models import F from django.db.models import F
from libs import JsonParser, Argument, json_response from libs import JsonParser, Argument, json_response, auth
from apps.app.models import App, Deploy, DeployExtend1, DeployExtend2 from apps.app.models import App, Deploy, DeployExtend1, DeployExtend2
from apps.config.models import Config from apps.config.models import Config
from apps.app.utils import fetch_versions, remove_repo from apps.app.utils import fetch_versions, remove_repo
@ -13,6 +13,7 @@ import re
class AppView(View): class AppView(View):
@auth('deploy.app.view|deploy.repository.view|deploy.request.view|config.app.view')
def get(self, request): def get(self, request):
query = {} query = {}
if not request.user.is_supper: if not request.user.is_supper:
@ -20,6 +21,7 @@ class AppView(View):
apps = App.objects.filter(**query) apps = App.objects.filter(**query)
return json_response(apps) return json_response(apps)
@auth('deploy.app.edit|config.app.add|config.app.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -42,6 +44,7 @@ class AppView(View):
app.save() app.save()
return json_response(error=error) return json_response(error=error)
@auth('deploy.app.edit|config.app.edit_config')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -68,6 +71,7 @@ class AppView(View):
app.save() app.save()
return json_response(error=error) return json_response(error=error)
@auth('deploy.app.del|config.app.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -82,6 +86,7 @@ class AppView(View):
class DeployView(View): class DeployView(View):
@auth('deploy.app.view|deploy.request.view')
def get(self, request): def get(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('app_id', type=int, required=False) Argument('app_id', type=int, required=False)
@ -95,6 +100,7 @@ class DeployView(View):
.order_by('-app__sort_id') .order_by('-app__sort_id')
return json_response(deploys) return json_response(deploys)
@auth('deploy.app.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -157,6 +163,7 @@ class DeployView(View):
DeployExtend2.objects.create(deploy=deploy, **extend_form) DeployExtend2.objects.create(deploy=deploy, **extend_form)
return json_response(error=error) return json_response(error=error)
@auth('deploy.app.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -171,6 +178,7 @@ class DeployView(View):
return json_response(error=error) return json_response(error=error)
@auth('deploy.app.config')
def get_versions(request, d_id): def get_versions(request, d_id):
deploy = Deploy.objects.filter(pk=d_id).first() deploy = Deploy.objects.filter(pk=d_id).first()
if not deploy: if not deploy:
@ -181,6 +189,7 @@ def get_versions(request, d_id):
return json_response({'branches': branches, 'tags': tags}) return json_response({'branches': branches, 'tags': tags})
@auth('deploy.app.config')
def kit_key(request): def kit_key(request):
api_key = AppSetting.get_default('api_key') api_key = AppSetting.get_default('api_key')
return json_response(api_key) return json_response(api_key)

View File

@ -3,7 +3,7 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from django.db.models import F from django.db.models import F
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument, auth
from apps.app.models import Deploy from apps.app.models import Deploy
from apps.config.models import * from apps.config.models import *
import json import json
@ -11,6 +11,7 @@ import re
class EnvironmentView(View): class EnvironmentView(View):
@auth('deploy.repository.view|deploy.request.view|config.env.view')
def get(self, request): def get(self, request):
query = {} query = {}
if not request.user.is_supper: if not request.user.is_supper:
@ -18,6 +19,7 @@ class EnvironmentView(View):
envs = Environment.objects.filter(**query) envs = Environment.objects.filter(**query)
return json_response(envs) return json_response(envs)
@auth('config.env.add|config.env.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -40,6 +42,7 @@ class EnvironmentView(View):
env.save() env.save()
return json_response(error=error) return json_response(error=error)
@auth('config.env.edit')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -60,6 +63,7 @@ class EnvironmentView(View):
env.save() env.save()
return json_response(error=error) return json_response(error=error)
@auth('config.env.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -74,10 +78,12 @@ class EnvironmentView(View):
class ServiceView(View): class ServiceView(View):
@auth('config.src.view')
def get(self, request): def get(self, request):
services = Service.objects.all() services = Service.objects.all()
return json_response(services) return json_response(services)
@auth('config.src.add|config.src.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -98,6 +104,7 @@ class ServiceView(View):
Service.objects.create(created_by=request.user, **form) Service.objects.create(created_by=request.user, **form)
return json_response(error=error) return json_response(error=error)
@auth('config.src.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -110,6 +117,7 @@ class ServiceView(View):
class ConfigView(View): class ConfigView(View):
@auth('config.src.view_config|config.app.view_config')
def get(self, request): def get(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='未指定操作对象'), Argument('id', type=int, help='未指定操作对象'),
@ -125,6 +133,7 @@ class ConfigView(View):
return json_response(data) return json_response(data)
return json_response(error=error) return json_response(error=error)
@auth('config.src.edit_config|config.app.edit_config')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('o_id', type=int, help='缺少必要参数'), Argument('o_id', type=int, help='缺少必要参数'),
@ -148,6 +157,7 @@ class ConfigView(View):
ConfigHistory.objects.create(action='1', env_id=env_id, **form) ConfigHistory.objects.create(action='1', env_id=env_id, **form)
return json_response(error=error) return json_response(error=error)
@auth('config.src.edit_config|config.app.edit_config')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='缺少必要参数'), Argument('id', type=int, help='缺少必要参数'),
@ -174,6 +184,7 @@ class ConfigView(View):
config.save() config.save()
return json_response(error=error) return json_response(error=error)
@auth('config.src.edit_config|config.app.edit_config')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='未指定操作对象') Argument('id', type=int, help='未指定操作对象')
@ -194,6 +205,7 @@ class ConfigView(View):
class HistoryView(View): class HistoryView(View):
@auth('config.src.view_config|config.app.view_config')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('o_id', type=int, help='缺少必要参数'), Argument('o_id', type=int, help='缺少必要参数'),
@ -211,6 +223,7 @@ class HistoryView(View):
return json_response(error=error) return json_response(error=error)
@auth('config.src.view_config|config.app.view_config')
def post_diff(request): def post_diff(request):
form, error = JsonParser( form, error = JsonParser(
Argument('o_id', type=int, help='缺少必要参数'), Argument('o_id', type=int, help='缺少必要参数'),
@ -228,6 +241,7 @@ def post_diff(request):
return json_response(error=error) return json_response(error=error)
@auth('config.src.edit_config|config.app.edit_config')
def parse_json(request): def parse_json(request):
form, error = JsonParser( form, error = JsonParser(
Argument('o_id', type=int, help='缺少必要参数'), Argument('o_id', type=int, help='缺少必要参数'),
@ -241,6 +255,7 @@ def parse_json(request):
return json_response(error=error) return json_response(error=error)
@auth('config.src.edit_config|config.app.edit_config')
def parse_text(request): def parse_text(request):
form, error = JsonParser( form, error = JsonParser(
Argument('o_id', type=int, help='缺少必要参数'), Argument('o_id', type=int, help='缺少必要参数'),

View File

@ -6,7 +6,7 @@ from django.db.models import F
from django.conf import settings from django.conf import settings
from django.http.response import HttpResponseBadRequest from django.http.response import HttpResponseBadRequest
from django_redis import get_redis_connection from django_redis import get_redis_connection
from libs import json_response, JsonParser, Argument, human_datetime, human_time from libs import json_response, JsonParser, Argument, human_datetime, human_time, auth
from apps.deploy.models import DeployRequest from apps.deploy.models import DeployRequest
from apps.app.models import Deploy, DeployExtend2 from apps.app.models import Deploy, DeployExtend2
from apps.repository.models import Repository from apps.repository.models import Repository
@ -21,6 +21,7 @@ import os
class RequestView(View): class RequestView(View):
@auth('deploy.request.view')
def get(self, request): def get(self, request):
data, query, counter = [], {}, {} data, query, counter = [], {}, {}
if not request.user.is_supper: if not request.user.is_supper:
@ -54,37 +55,7 @@ class RequestView(View):
data.append(tmp) data.append(tmp)
return json_response(data) return json_response(data)
def put(self, request): @auth('deploy.request.del')
form, error = JsonParser(
Argument('id', type=int, help='缺少必要参数'),
Argument('action', filter=lambda x: x in ('check', 'do'), help='参数错误')
).parse(request.body)
if error is None:
req = DeployRequest.objects.filter(pk=form.id).first()
if not req:
return json_response(error='未找到指定发布申请')
pre_req = DeployRequest.objects.filter(
deploy_id=req.deploy_id,
type='1',
id__lt=req.id,
version__isnull=False).first()
if not pre_req:
return json_response(error='未找到该应用可以用于回滚的版本')
if form.action == 'check':
return json_response({'date': pre_req.created_at, 'name': pre_req.name})
DeployRequest.objects.create(
deploy_id=req.deploy_id,
name=f'{req.name} - 回滚',
type='2',
extra=pre_req.extra,
host_ids=req.host_ids,
status='0' if pre_req.deploy.is_audit else '1',
desc='自动回滚至该应用的上个版本',
version=pre_req.version,
created_by=request.user
)
return json_response(error=error)
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -123,6 +94,7 @@ class RequestView(View):
class RequestDetailView(View): class RequestDetailView(View):
@auth('deploy.request.view')
def get(self, request, r_id): def get(self, request, r_id):
req = DeployRequest.objects.filter(pk=r_id).first() req = DeployRequest.objects.filter(pk=r_id).first()
if not req: if not req:
@ -160,6 +132,7 @@ class RequestDetailView(View):
outputs['local'].update(step=100, data=f'{human_time()} 已构建完成忽略执行。') outputs['local'].update(step=100, data=f'{human_time()} 已构建完成忽略执行。')
return json_response(response) return json_response(response)
@auth('deploy.request.do')
def post(self, request, r_id): def post(self, request, r_id):
query = {'pk': r_id} query = {'pk': r_id}
if not request.user.is_supper: if not request.user.is_supper:
@ -194,6 +167,7 @@ class RequestDetailView(View):
return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs}) return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs})
return json_response({'outputs': outputs}) return json_response({'outputs': outputs})
@auth('deploy.request.approve')
def patch(self, request, r_id): def patch(self, request, r_id):
form, error = JsonParser( form, error = JsonParser(
Argument('reason', required=False), Argument('reason', required=False),
@ -216,6 +190,7 @@ class RequestDetailView(View):
return json_response(error=error) return json_response(error=error)
@auth('deploy.request.add|deploy.request.edit')
def post_request_ext1(request): def post_request_ext1(request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -264,6 +239,7 @@ def post_request_ext1(request):
return json_response(error=error) return json_response(error=error)
@auth('deploy.request.do')
def post_request_ext1_rollback(request): def post_request_ext1_rollback(request):
form, error = JsonParser( form, error = JsonParser(
Argument('request_id', type=int, help='请选择要回滚的版本'), Argument('request_id', type=int, help='请选择要回滚的版本'),
@ -295,6 +271,7 @@ def post_request_ext1_rollback(request):
return json_response(error=error) return json_response(error=error)
@auth('deploy.request.add|deploy.request.edit')
def post_request_ext2(request): def post_request_ext2(request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -334,6 +311,7 @@ def post_request_ext2(request):
return json_response(error=error) return json_response(error=error)
@auth('deploy.request.view')
def get_request_info(request): def get_request_info(request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误') Argument('id', type=int, help='参数错误')
@ -346,6 +324,7 @@ def get_request_info(request):
return json_response(error=error) return json_response(error=error)
@auth('deploy.request.add')
def do_upload(request): def do_upload(request):
repos_dir = settings.REPOS_DIR repos_dir = settings.REPOS_DIR
file = request.FILES['file'] file = request.FILES['file']

View File

@ -4,7 +4,7 @@
from django.views.generic import View from django.views.generic import View
from django_redis import get_redis_connection from django_redis import get_redis_connection
from django.conf import settings from django.conf import settings
from libs import json_response, JsonParser, Argument, human_datetime from libs import json_response, JsonParser, Argument, human_datetime, auth
from apps.exec.models import ExecTemplate from apps.exec.models import ExecTemplate
from apps.host.models import Host from apps.host.models import Host
from apps.account.utils import has_host_perm from apps.account.utils import has_host_perm
@ -13,11 +13,13 @@ import json
class TemplateView(View): class TemplateView(View):
@auth('exec.template.view')
def get(self, request): def get(self, request):
templates = ExecTemplate.objects.all() templates = ExecTemplate.objects.all()
types = [x['type'] for x in templates.order_by('type').values('type').distinct()] types = [x['type'] for x in templates.order_by('type').values('type').distinct()]
return json_response({'types': types, 'templates': [x.to_dict() for x in templates]}) return json_response({'types': types, 'templates': [x.to_dict() for x in templates]})
@auth('exec.template.add|exec.template.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -36,6 +38,7 @@ class TemplateView(View):
ExecTemplate.objects.create(**form) ExecTemplate.objects.create(**form)
return json_response(error=error) return json_response(error=error)
@auth('exec.template.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -45,6 +48,7 @@ class TemplateView(View):
return json_response(error=error) return json_response(error=error)
@auth('exec.task.do')
def do_task(request): def do_task(request):
form, error = JsonParser( form, error = JsonParser(
Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择执行主机'), Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择执行主机'),

View File

@ -6,12 +6,13 @@ from django_redis import get_redis_connection
from apps.host.models import Host from apps.host.models import Host
from apps.account.utils import has_host_perm from apps.account.utils import has_host_perm
from apps.file.utils import FileResponseAfter, fetch_dir_list from apps.file.utils import FileResponseAfter, fetch_dir_list
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument, auth
from functools import partial from functools import partial
import os import os
class FileView(View): class FileView(View):
@auth('host.console.list')
def get(self, request): def get(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -29,6 +30,7 @@ class FileView(View):
class ObjectView(View): class ObjectView(View):
@auth('host.console.list')
def get(self, request): def get(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -47,6 +49,7 @@ class ObjectView(View):
return FileResponseAfter(ssh_cli.close, f, as_attachment=True, filename=filename) return FileResponseAfter(ssh_cli.close, f, as_attachment=True, filename=filename)
return json_response(error=error) return json_response(error=error)
@auth('host.console.upload')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -68,6 +71,7 @@ class ObjectView(View):
ssh.put_file_by_fl(file, f'{form.path}/{file.name}', callback=callback) ssh.put_file_by_fl(file, f'{form.path}/{file.name}', callback=callback)
return json_response(error=error) return json_response(error=error)
@auth('host.console.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),

View File

@ -11,10 +11,12 @@ from apps.deploy.models import Deploy, DeployRequest
from apps.account.utils import get_host_perms from apps.account.utils import get_host_perms
from libs.utils import json_response, human_date, parse_time from libs.utils import json_response, human_date, parse_time
from libs.parser import JsonParser, Argument from libs.parser import JsonParser, Argument
from libs.decorators import auth
from datetime import datetime, timedelta from datetime import datetime, timedelta
import json import json
@auth('dashboard.dashboard.view')
def get_statistic(request): def get_statistic(request):
if request.user.is_supper: if request.user.is_supper:
app = App.objects.count() app = App.objects.count()
@ -32,6 +34,7 @@ def get_statistic(request):
return json_response(data) return json_response(data)
@auth('dashboard.dashboard.view')
def get_alarm(request): def get_alarm(request):
form, error = JsonParser( form, error = JsonParser(
Argument('type', required=False), Argument('type', required=False),
@ -49,6 +52,7 @@ def get_alarm(request):
return json_response(error=error) return json_response(error=error)
@auth('dashboard.dashboard.view')
def get_request(request): def get_request(request):
form, error = JsonParser( form, error = JsonParser(
Argument('duration', type=list, help='参数错误') Argument('duration', type=list, help='参数错误')
@ -64,6 +68,7 @@ def get_request(request):
return json_response(error=error) return json_response(error=error)
@auth('dashboard.dashboard.view')
def get_deploy(request): def get_deploy(request):
host = Host.objects.filter(deleted_at__isnull=True).count() host = Host.objects.filter(deleted_at__isnull=True).count()
data = {x.id: {'name': x.name, 'count': 0} for x in App.objects.all()} data = {x.id: {'name': x.name, 'count': 0} for x in App.objects.all()}
@ -71,4 +76,3 @@ def get_deploy(request):
data[dep.app_id]['count'] += len(json.loads(dep.host_ids)) data[dep.app_id]['count'] += len(json.loads(dep.host_ids))
data = filter(lambda x: x['count'], data.values()) data = filter(lambda x: x['count'], data.values())
return json_response({'host': host, 'res': list(data)}) return json_response({'host': host, 'res': list(data)})

View File

@ -1,12 +1,13 @@
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument, auth
from apps.host.models import Host, HostExtend, Group from apps.host.models import Host, HostExtend, Group
from apps.host import utils from apps.host import utils
import json import json
@auth('host.host.add')
def get_regions(request): def get_regions(request):
form, error = JsonParser( form, error = JsonParser(
Argument('type', filter=lambda x: x in ('ali', 'tencent'), help='参数错误'), Argument('type', filter=lambda x: x in ('ali', 'tencent'), help='参数错误'),
@ -25,6 +26,7 @@ def get_regions(request):
return json_response(error=error) return json_response(error=error)
@auth('host.host.add')
def cloud_import(request): def cloud_import(request):
form, error = JsonParser( form, error = JsonParser(
Argument('type', filter=lambda x: x in ('ali', 'tencent'), help='参数错误'), Argument('type', filter=lambda x: x in ('ali', 'tencent'), help='参数错误'),

View File

@ -2,13 +2,14 @@
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from libs import json_response, JsonParser, Argument, human_datetime from libs import json_response, JsonParser, Argument, human_datetime, auth
from apps.host.models import Host, HostExtend from apps.host.models import Host, HostExtend
from apps.host.utils import check_os_type, fetch_host_extend from apps.host.utils import check_os_type, fetch_host_extend
import json import json
class ExtendView(View): class ExtendView(View):
@auth('host.host.add|host.host.edit')
def get(self, request): def get(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('host_id', type=int, help='参数错误') Argument('host_id', type=int, help='参数错误')
@ -24,6 +25,7 @@ class ExtendView(View):
return json_response(response) return json_response(response)
return json_response(error=error) return json_response(error=error)
@auth('host.host.add|host.host.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('host_id', type=int, help='参数错误'), Argument('host_id', type=int, help='参数错误'),

View File

@ -3,7 +3,7 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from django.db.models import F from django.db.models import F
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument, auth
from apps.host.models import Group from apps.host.models import Group
from apps.account.models import Role from apps.account.models import Role
@ -39,6 +39,7 @@ def filter_by_perm(data, result, ids):
class GroupView(View): class GroupView(View):
@auth('host.host.view|host.console.view|exec.task.do')
def get(self, request): def get(self, request):
with_hosts = request.GET.get('with_hosts') with_hosts = request.GET.get('with_hosts')
data, data2 = dict(), dict() data, data2 = dict(), dict()
@ -56,6 +57,7 @@ class GroupView(View):
merge_children(data2, '', tree_data) merge_children(data2, '', tree_data)
return json_response({'treeData': tree_data, 'groups': data2}) return json_response({'treeData': tree_data, 'groups': data2})
@auth('admin')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -71,6 +73,7 @@ class GroupView(View):
group.save() group.save()
return json_response(error=error) return json_response(error=error)
@auth('admin')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('s_id', type=int, help='参数错误'), Argument('s_id', type=int, help='参数错误'),
@ -100,6 +103,7 @@ class GroupView(View):
src.save() src.save()
return json_response(error=error) return json_response(error=error)
@auth('admin')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误') Argument('id', type=int, help='参数错误')

View File

@ -4,7 +4,7 @@
from django.views.generic import View from django.views.generic import View
from django.db.models import F from django.db.models import F
from django.http.response import HttpResponseBadRequest from django.http.response import HttpResponseBadRequest
from libs import json_response, JsonParser, Argument, AttrDict from libs import json_response, JsonParser, Argument, AttrDict, auth
from apps.setting.utils import AppSetting from apps.setting.utils import AppSetting
from apps.account.utils import get_host_perms from apps.account.utils import get_host_perms
from apps.host.models import Host, Group from apps.host.models import Host, Group
@ -20,6 +20,7 @@ import uuid
class HostView(View): class HostView(View):
@auth('host.host.view|exec.task.do')
def get(self, request): def get(self, request):
hosts = Host.objects.select_related('hostextend') hosts = Host.objects.select_related('hostextend')
if not request.user.is_supper: if not request.user.is_supper:
@ -29,6 +30,7 @@ class HostView(View):
hosts[rel.host_id]['group_ids'].append(rel.group_id) hosts[rel.host_id]['group_ids'].append(rel.group_id)
return json_response(list(hosts.values())) return json_response(list(hosts.values()))
@auth('host.host.add|host.host.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -76,6 +78,7 @@ class HostView(View):
return json_response(response) return json_response(response)
return json_response(error=error) return json_response(error=error)
@auth('admin')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择主机'), Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择主机'),
@ -93,6 +96,7 @@ class HostView(View):
s_group.hosts.remove(*form.host_ids) s_group.hosts.remove(*form.host_ids)
return json_response(error=error) return json_response(error=error)
@auth('host.host.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -122,6 +126,7 @@ class HostView(View):
return json_response(error=error) return json_response(error=error)
@auth('host.host.add')
def post_import(request): def post_import(request):
group_id = request.POST.get('group_id') group_id = request.POST.get('group_id')
file = request.FILES['file'] file = request.FILES['file']
@ -152,6 +157,7 @@ def post_import(request):
return json_response(summary) return json_response(summary)
@auth('host.host.add')
def post_parse(request): def post_parse(request):
file = request.FILES['file'] file = request.FILES['file']
if file: if file:
@ -161,6 +167,7 @@ def post_parse(request):
return HttpResponseBadRequest() return HttpResponseBadRequest()
@auth('host.host.add')
def batch_valid(request): def batch_valid(request):
form, error = JsonParser( form, error = JsonParser(
Argument('password', required=False), Argument('password', required=False),

View File

@ -2,7 +2,7 @@
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View from django.views.generic import View
from libs import json_response, JsonParser, Argument, human_datetime from libs import json_response, JsonParser, Argument, human_datetime, auth
from apps.monitor.models import Detection from apps.monitor.models import Detection
from django_redis import get_redis_connection from django_redis import get_redis_connection
from django.conf import settings from django.conf import settings
@ -11,11 +11,13 @@ import json
class DetectionView(View): class DetectionView(View):
@auth('dashboard.dashboard.view|monitor.monitor.view')
def get(self, request): def get(self, request):
detections = Detection.objects.all() detections = Detection.objects.all()
groups = [x['group'] for x in detections.order_by('group').values('group').distinct()] groups = [x['group'] for x in detections.order_by('group').values('group').distinct()]
return json_response({'groups': groups, 'detections': [x.to_view() for x in detections]}) return json_response({'groups': groups, 'detections': [x.to_view() for x in detections]})
@auth('monitor.monitor.add|monitor.monitor.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -53,6 +55,7 @@ class DetectionView(View):
rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form)) rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
return json_response(error=error) return json_response(error=error)
@auth('monitor.monitor.edit')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象'), Argument('id', type=int, help='请指定操作对象'),
@ -71,6 +74,7 @@ class DetectionView(View):
rds_cli.lpush(settings.MONITOR_KEY, json.dumps(message)) rds_cli.lpush(settings.MONITOR_KEY, json.dumps(message))
return json_response(error=error) return json_response(error=error)
@auth('monitor.monitor.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -84,6 +88,7 @@ class DetectionView(View):
return json_response(error=error) return json_response(error=error)
@auth('monitor.monitor.add|monitor.monitor.edit')
def run_test(request): def run_test(request):
form, error = JsonParser( form, error = JsonParser(
Argument('type', help='请选择监控类型'), Argument('type', help='请选择监控类型'),

View File

@ -5,7 +5,7 @@ from django.views.generic import View
from django.db.models import F from django.db.models import F
from django.conf import settings from django.conf import settings
from django_redis import get_redis_connection from django_redis import get_redis_connection
from libs import json_response, JsonParser, Argument, human_time, AttrDict from libs import json_response, JsonParser, Argument, human_time, AttrDict, auth
from apps.repository.models import Repository from apps.repository.models import Repository
from apps.deploy.models import DeployRequest from apps.deploy.models import DeployRequest
from apps.repository.utils import dispatch from apps.repository.utils import dispatch
@ -15,6 +15,7 @@ import json
class RepositoryView(View): class RepositoryView(View):
@auth('deploy.repository.view')
def get(self, request): def get(self, request):
deploy_id = request.GET.get('deploy_id') deploy_id = request.GET.get('deploy_id')
data = Repository.objects.annotate( data = Repository.objects.annotate(
@ -35,6 +36,7 @@ class RepositoryView(View):
response[item.app_id] = tmp response[item.app_id] = tmp
return json_response(list(response.values())) return json_response(list(response.values()))
@auth('deploy.repository.add')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('deploy_id', type=int, help='参数错误'), Argument('deploy_id', type=int, help='参数错误'),
@ -57,6 +59,7 @@ class RepositoryView(View):
return json_response(rep.to_view()) return json_response(rep.to_view())
return json_response(error=error) return json_response(error=error)
@auth('deploy.repository.add|deploy.repository.build')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='参数错误'), Argument('id', type=int, help='参数错误'),
@ -71,6 +74,7 @@ class RepositoryView(View):
return json_response(rep.to_view()) return json_response(rep.to_view())
return json_response(error=error) return json_response(error=error)
@auth('deploy.repository.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -85,6 +89,7 @@ class RepositoryView(View):
return json_response(error=error) return json_response(error=error)
@auth('deploy.repository.view')
def get_requests(request): def get_requests(request):
form, error = JsonParser( form, error = JsonParser(
Argument('repository_id', type=int, help='参数错误') Argument('repository_id', type=int, help='参数错误')
@ -99,6 +104,7 @@ def get_requests(request):
return json_response(requests) return json_response(requests)
@auth('deploy.repository.view')
def get_detail(request, r_id): def get_detail(request, r_id):
repository = Repository.objects.filter(pk=r_id).first() repository = Repository.objects.filter(pk=r_id).first()
if not repository: if not repository:

View File

@ -10,16 +10,18 @@ from apps.schedule.models import Task, History
from apps.schedule.executors import local_executor, host_executor from apps.schedule.executors import local_executor, host_executor
from apps.host.models import Host from apps.host.models import Host
from django.conf import settings from django.conf import settings
from libs import json_response, JsonParser, Argument, human_datetime from libs import json_response, JsonParser, Argument, human_datetime, auth
import json import json
class Schedule(View): class Schedule(View):
@auth('schedule.schedule.view')
def get(self, request): def get(self, request):
tasks = Task.objects.all() tasks = Task.objects.all()
types = [x['type'] for x in tasks.order_by('type').values('type').distinct()] types = [x['type'] for x in tasks.order_by('type').values('type').distinct()]
return json_response({'types': types, 'tasks': [x.to_dict() for x in tasks]}) return json_response({'types': types, 'tasks': [x.to_dict() for x in tasks]})
@auth('schedule.schedule.add|schedule.schedule.edit')
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
@ -61,6 +63,7 @@ class Schedule(View):
Task.objects.create(created_by=request.user, **form) Task.objects.create(created_by=request.user, **form)
return json_response(error=error) return json_response(error=error)
@auth('schedule.schedule.edit')
def patch(self, request): def patch(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象'), Argument('id', type=int, help='请指定操作对象'),
@ -81,6 +84,7 @@ class Schedule(View):
task.save() task.save()
return json_response(error=error) return json_response(error=error)
@auth('schedule.schedule.del')
def delete(self, request): def delete(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, help='请指定操作对象') Argument('id', type=int, help='请指定操作对象')
@ -96,6 +100,7 @@ class Schedule(View):
class HistoryView(View): class HistoryView(View):
@auth('schedule.schedule.view')
def get(self, request, t_id): def get(self, request, t_id):
task = Task.objects.filter(pk=t_id).first() task = Task.objects.filter(pk=t_id).first()
if not task: if not task:
@ -108,6 +113,7 @@ class HistoryView(View):
histories = History.objects.filter(task_id=t_id) histories = History.objects.filter(task_id=t_id)
return json_response([x.to_list() for x in histories]) return json_response([x.to_list() for x in histories])
@auth('schedule.schedule.edit')
def post(self, request, t_id): def post(self, request, t_id):
task = Task.objects.filter(pk=t_id).first() task = Task.objects.filter(pk=t_id).first()
if not task: if not task:
@ -156,6 +162,7 @@ class HistoryView(View):
return data return data
@auth('schedule.schedule.add|schedule.schedule.edit')
def next_run_time(request): def next_run_time(request):
form, error = JsonParser( form, error = JsonParser(
Argument('rule', help='参数错误'), Argument('rule', help='参数错误'),

View File

@ -3,19 +3,19 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
import django import django
from django.core.cache import cache from django.core.cache import cache
from django.views.generic import View
from django.conf import settings from django.conf import settings
from libs import JsonParser, Argument, json_response from libs import JsonParser, Argument, json_response, auth
from libs.utils import generate_random_str from libs.utils import generate_random_str
from libs.mail import Mail from libs.mail import Mail
from libs.spug import send_login_wx_code from libs.spug import send_login_wx_code
from libs.mixins import AdminView
from apps.setting.utils import AppSetting from apps.setting.utils import AppSetting
from apps.setting.models import Setting from apps.setting.models import Setting
import platform import platform
import ldap import ldap
class SettingView(View): class SettingView(AdminView):
def get(self, request): def get(self, request):
data = Setting.objects.all() data = Setting.objects.all()
return json_response([x.to_view() for x in data]) return json_response([x.to_view() for x in data])
@ -30,7 +30,7 @@ class SettingView(View):
return json_response(error=error) return json_response(error=error)
class MFAView(View): class MFAView(AdminView):
def get(self, request): def get(self, request):
if not request.user.wx_token: if not request.user.wx_token:
return json_response(error='检测到当前账户未配置微信Token请配置后再尝试启用MFA认证否则可能造成系统无法正常登录。') return json_response(error='检测到当前账户未配置微信Token请配置后再尝试启用MFA认证否则可能造成系统无法正常登录。')
@ -61,6 +61,7 @@ class MFAView(View):
return json_response(error=error) return json_response(error=error)
@auth('admin')
def ldap_test(request): def ldap_test(request):
form, error = JsonParser( form, error = JsonParser(
Argument('server'), Argument('server'),
@ -79,6 +80,7 @@ def ldap_test(request):
return json_response(error=error) return json_response(error=error)
@auth('admin')
def email_test(request): def email_test(request):
form, error = JsonParser( form, error = JsonParser(
Argument('server', help='请输入邮件服务地址'), Argument('server', help='请输入邮件服务地址'),
@ -97,6 +99,7 @@ def email_test(request):
return json_response(error=error) return json_response(error=error)
@auth('admin')
def mfa_test(request): def mfa_test(request):
if not request.user.wx_token: if not request.user.wx_token:
return json_response(error='检测到当前账户未配置微信Token请配置后再尝试启用MFA认证否则可能造成系统无法正常登录。') return json_response(error='检测到当前账户未配置微信Token请配置后再尝试启用MFA认证否则可能造成系统无法正常登录。')
@ -106,6 +109,7 @@ def mfa_test(request):
return json_response() return json_response()
@auth('admin')
def get_about(request): def get_about(request):
return json_response({ return json_response({
'python_version': platform.python_version(), 'python_version': platform.python_version(),

View File

@ -5,35 +5,20 @@ from functools import wraps
from .utils import json_response from .utils import json_response
def permission_required_supper(view_func): def auth(perm_list):
@wraps(view_func)
def wrapper(*args, **kwargs):
request = None
for item in args:
if hasattr(item, 'user'):
request = item
break
if request is None or not request.user.is_supper:
return json_response(error='需要管理员权限')
return view_func(*args, **kwargs)
return wrapper
def permission_required(perm_list):
def decorate(view_func): def decorate(view_func):
codes = (perm_list,) if isinstance(perm_list, str) else perm_list codes = perm_list.split('|')
@wraps(view_func) @wraps(view_func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
request = None user = None
for item in args: for item in args[:2]:
if hasattr(item, 'user'): if hasattr(item, 'user'):
request = item user = item.user
break break
if request is None or (not request.user.is_supper and not request.user.has_perms(codes)): if user and user.has_perms(codes):
return json_response(error='拒绝访问')
return view_func(*args, **kwargs) return view_func(*args, **kwargs)
return json_response(error='权限拒绝')
return wrapper return wrapper

View File

@ -1,6 +1,7 @@
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.views.generic import View
from .utils import json_response from .utils import json_response
@ -24,38 +25,9 @@ class ModelMixin(object):
self.save() self.save()
# 使用该混入类需要request.user对象实现has_perms方法 class AdminView(View):
class PermissionMixin(object):
"""
CBV mixin which verifies that the current user has all specified
permissions.
"""
permission_required = None
def get_permission_required(self):
"""
Override this method to override the permission_required attribute.
Must return an iterable.
"""
if self.permission_required is None:
raise AttributeError(
'{0} is missing the permission_required attribute. Define {0}.permission_required, or override '
'{0}.get_permission_required().'.format(self.__class__.__name__)
)
if isinstance(self.permission_required, str):
perms = (self.permission_required,)
else:
perms = self.permission_required
return perms
def has_permission(self):
"""
Override this method to customize the way permissions are checked.
"""
perms = self.get_permission_required()
return self.request.user.has_perms(perms)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not self.has_permission(): if hasattr(request, 'user') and request.user.is_supper:
return json_response(error='拒绝访问') return super().dispatch(request, *args, **kwargs)
return super(PermissionMixin, self).dispatch(request, *args, **kwargs) else:
return json_response(error='权限拒绝')

View File

@ -3,15 +3,22 @@
* Copyright (c) <spug.dev@gmail.com> * Copyright (c) <spug.dev@gmail.com>
* Released under the AGPL-3.0 License. * Released under the AGPL-3.0 License.
*/ */
import React from 'react'; import React, {useEffect} from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Modal, Steps } from 'antd'; import { Modal, Steps } from 'antd';
import Step1 from './Step1'; import Step1 from './Step1';
import Step2 from './Step2'; import Step2 from './Step2';
import store from './store'; import store from './store';
import styles from './index.module.css'; import styles from './index.module.css';
import groupStore from '../alarm/group/store';
export default observer(function () { export default observer(function () {
useEffect(() => {
if (groupStore.records.length === 0) {
groupStore.fetchRecords();
}
}, [])
return ( return (
<Modal <Modal
visible visible

View File

@ -9,36 +9,13 @@ import { Table, Modal, Radio, Tag, message } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { Action, AuthButton, TableCard } from 'components'; import { Action, AuthButton, TableCard } from 'components';
import { http, hasPermission } from 'libs'; import { http, hasPermission } from 'libs';
import groupStore from '../alarm/group/store';
import hostStore from '../host/store';
import store from './store'; import store from './store';
@observer @observer
class ComTable extends React.Component { class ComTable extends React.Component {
constructor(props) {
super(props);
this.state = {
hosts: {}
}
}
componentDidMount() { componentDidMount() {
store.fetchRecords(); store.fetchRecords();
if (groupStore.records.length === 0) groupStore.fetchRecords();
if (!hostStore.records || hostStore.records.length === 0) {
hostStore.fetchRecords().then(this._handleHosts)
} else {
this._handleHosts()
} }
}
_handleHosts = () => {
const tmp = {};
for (let item of hostStore.records) {
tmp[item.id] = item
}
this.setState({hosts: tmp})
};
handleActive = (text) => { handleActive = (text) => {
Modal.confirm({ Modal.confirm({

View File

@ -22,7 +22,7 @@ class ComTable extends React.Component {
moreMenus = (info) => ( moreMenus = (info) => (
<Menu> <Menu>
<Menu.Item> <Menu.Item>
<LinkButton onClick={() => this.handleTest(info)}>执行测试</LinkButton> <LinkButton auth="schedule.schedule.edit" onClick={() => this.handleTest(info)}>执行测试</LinkButton>
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
<LinkButton <LinkButton