Пример #1
0
 def patch(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='参数错误'),
         Argument('page_perms', type=dict, required=False),
         Argument('deploy_perms', type=dict,
                  required=False)).parse(request.body)
     if error is None:
         role = Role.objects.filter(pk=form.pop('id')).first()
         if not role:
             return json_response(error='未找到指定角色')
         if form.page_perms is not None:
             role.page_perms = json.dumps(form.page_perms)
         if form.deploy_perms is not None:
             role.deploy_perms = json.dumps(form.deploy_perms)
         role.user_set.update(token_expired=0)
         role.save()
     return json_response(error=error)
Пример #2
0
 def get(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='未指定操作对象'),
         Argument('type',
                  filter=lambda x: x in dict(Config.TYPES),
                  help='缺少必要参数'),
         Argument('env_id', type=int, help='缺少必要参数'),
     ).parse(request.GET)
     if error is None:
         form.o_id, data = form.pop('id'), []
         for item in Config.objects.filter(**form).annotate(
                 update_user=F('updated_by__nickname')):
             tmp = item.to_dict()
             tmp['update_user'] = item.update_user
             data.append(tmp)
         return json_response(data)
     return json_response(error=error)
Пример #3
0
 def post(self, request):
     form, error = JsonParser(
         Argument('o_id', type=int, help='缺少必要参数'),
         Argument('env_id', type=int, help='缺少必要参数'),
         Argument('type',
                  filter=lambda x: x in dict(Config.TYPES),
                  help='缺少必要参数')).parse(request.body)
     if error is None:
         data = []
         for item in ConfigHistory.objects.filter(**form).annotate(
                 update_user=F('updated_by__nickname')):
             tmp = item.to_dict()
             tmp['action_alias'] = item.get_action_display()
             tmp['update_user'] = item.update_user
             data.append(tmp)
         return json_response(data)
     return json_response(error=error)
Пример #4
0
 def patch(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='请指定操作对象'),
         Argument('is_active', type=bool, required=False)
     ).parse(request.body, True)
     if error is None:
         Task.objects.filter(pk=form.id).update(**form)
         if form.get('is_active') is not None:
             if form.is_active:
                 task = Task.objects.filter(pk=form.id).first()
                 message = {'id': form.id, 'action': 'add'}
                 message.update(task.to_dict(selects=('trigger', 'trigger_args', 'command', 'targets')))
             else:
                 message = {'id': form.id, 'action': 'remove'}
             rds_cli = get_redis_connection()
             rds_cli.lpush(settings.SCHEDULE_KEY, json.dumps(message))
     return json_response(error=error)
Пример #5
0
 def post(self, request):
     form, error = JsonParser(Argument('id', type=int, required=False),
                              Argument('name', help='请输入服务名称'),
                              Argument('key', help='请输入唯一标识符'),
                              Argument('desc',
                                       required=False)).parse(request.body)
     if error is None:
         app = App.objects.filter(key=form.key).first()
         if app and app.id != form.id:
             return json_response(error=f'唯一标识符 {form.key} 已存在,请更改后重试')
         if form.id:
             App.objects.filter(pk=form.id).update(**form)
         else:
             app = App.objects.create(created_by=request.user, **form)
             if request.user.role:
                 request.user.role.add_deploy_perm('apps', app.id)
     return json_response(error=error)
Пример #6
0
 def get(self, request):
     form, error = JsonParser(Argument('id', type=int, help='参数错误'),
                              Argument('file',
                                       help='请输入文件路径')).parse(request.GET)
     if error is None:
         host = Host.objects.filter(pk=1).first()
         if not host:
             return json_response(error='未找到指定主机')
         filename = os.path.basename(form.file)
         cli = host.get_ssh().get_client()
         sftp = cli.open_sftp()
         f = sftp.open(form.file)
         return FileResponseAfter(cli.close,
                                  f,
                                  as_attachment=True,
                                  filename=filename)
     return json_response(error=error)
Пример #7
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('name', help='请输入联系人姓名'),
         Argument('phone', required=False),
         Argument('email', required=False),
         Argument('ding', required=False),
         Argument('wx_token', required=False),
         Argument('qy_wx', required=False),
     ).parse(request.body)
     if error is None:
         if form.id:
             Contact.objects.filter(pk=form.id).update(**form)
         else:
             form.created_by = request.user
             Contact.objects.create(**form)
     return json_response(error=error)
Пример #8
0
def post_diff(request):
    form, error = JsonParser(
        Argument('o_id', type=int, help='缺少必要参数'),
        Argument('type',
                 filter=lambda x: x in dict(Config.TYPES),
                 help='缺少必要参数'),
        Argument('envs', type=list, filter=lambda x: len(x), help='缺少必要参数'),
    ).parse(request.body)
    if error is None:
        data, form.env_id__in = {}, form.pop('envs')
        for item in Config.objects.filter(**form).order_by('key'):
            if item.key in data:
                data[item.key][item.env_id] = item.value
            else:
                data[item.key] = {'key': item.key, item.env_id: item.value}
        return json_response(list(data.values()))
    return json_response(error=error)
Пример #9
0
def post_request_ext2(request):
    form, error = JsonParser(
        Argument('id', type=int, required=False),
        Argument('deploy_id', type=int, help='缺少必要参数'),
        Argument('name', help='请输申请标题'),
        Argument('host_ids',
                 type=list,
                 filter=lambda x: len(x),
                 help='请选择要部署的主机'),
        Argument('extra', type=dict, required=False),
        Argument('version', default=''),
        Argument('type', default='1'),
        Argument('plan', required=False),
        Argument('desc', required=False),
    ).parse(request.body)
    if error is None:
        deploy = Deploy.objects.filter(pk=form.deploy_id).first()
        if not deploy:
            return json_response(error='未找到该发布配置')
        extra = form.pop('extra')
        if DeployExtend2.objects.filter(
                deploy=deploy,
                host_actions__contains='"src_mode": "1"').exists():
            if not extra:
                return json_response(
                    error='该应用的发布配置中使用了数据传输动作且设置为发布时上传,请上传要传输的数据')
            form.spug_version = extra['path']
            form.extra = json.dumps(extra)
        else:
            form.spug_version = Repository.make_spug_version(deploy.id)
        form.name = form.name.replace("'", '')
        form.status = '0' if deploy.is_audit else '1'
        form.host_ids = json.dumps(form.host_ids)
        if form.id:
            req = DeployRequest.objects.get(pk=form.id)
            is_required_notify = deploy.is_audit and req.status == '-1'
            DeployRequest.objects.filter(pk=form.id).update(
                created_by=request.user, reason=None, **form)
        else:
            req = DeployRequest.objects.create(created_by=request.user, **form)
            is_required_notify = deploy.is_audit
        if is_required_notify:
            Thread(target=Helper.send_deploy_notify,
                   args=(req, 'approve_req')).start()
    return json_response(error=error)
Пример #10
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('type', help='请输入任务类型'),
         Argument('name', help='请输入任务名称'),
         Argument('command', help='请输入任务内容'),
         Argument('targets',
                  type=list,
                  filter=lambda x: len(x),
                  help='请选择执行对象'),
         Argument('trigger',
                  filter=lambda x: x in dict(Task.TRIGGERS),
                  help='请选择触发器类型'),
         Argument('trigger_args', help='请输入触发器参数'),
         Argument('desc', required=False),
     ).parse(request.body)
     if error is None:
         form.targets = json.dumps(form.targets)
         if form.trigger == 'cron':
             args = json.loads(form.trigger_args)['rule'].split()
             if len(args) != 5:
                 return json_response(error='无效的执行规则,请更正后再试')
             minute, hour, day, month, week = args
             try:
                 CronTrigger(minute=minute,
                             hour=hour,
                             day=day,
                             month=month,
                             week=week)
             except ValueError:
                 return json_response(error='无效的执行规则,请更正后再试')
         if form.id:
             Task.objects.filter(pk=form.id).update(
                 updated_at=human_datetime(),
                 updated_by=request.user,
                 **form)
             task = Task.objects.filter(pk=form.id).first()
             if task and task.is_active:
                 form.action = 'modify'
                 form.targets = json.loads(form.targets)
                 rds_cli = get_redis_connection()
                 rds_cli.lpush(settings.SCHEDULE_KEY, json.dumps(form))
         else:
             Task.objects.create(created_by=request.user, **form)
     return json_response(error=error)
Пример #11
0
    def post(self, request):
        form, error = JsonParser(Argument('id', type=int, required=False),
                                 Argument('name', help='请输入服务名称'),
                                 Argument('key', help='请输入唯一标识符'),
                                 Argument('desc',
                                          required=False)).parse(request.body)
        if error is None:
            if not re.fullmatch(r'[-\w]+', form.key, re.ASCII):
                return json_response(error='标识符必须为字母、数字、-和下划线的组合')

            service = Service.objects.filter(key=form.key).first()
            if service and service.id != form.id:
                return json_response(error=f'唯一标识符 {form.key} 已存在,请更改后重试')
            if form.id:
                Service.objects.filter(pk=form.id).update(**form)
            else:
                Service.objects.create(created_by=request.user, **form)
        return json_response(error=error)
Пример #12
0
 def patch(self, request, r_id):
     form, error = JsonParser(Argument('reason', required=False),
                              Argument('is_pass', type=bool,
                                       help='参数错误')).parse(request.body)
     if error is None:
         req = DeployRequest.objects.filter(pk=r_id).first()
         if not req:
             return json_response(error='未找到指定申请')
         if not form.is_pass and not form.reason:
             return json_response(error='请输入驳回原因')
         if req.status != '0':
             return json_response(error='该申请当前状态不允许审核')
         req.approve_at = human_datetime()
         req.approve_by = request.user
         req.status = '1' if form.is_pass else '-1'
         req.reason = form.reason
         req.save()
     return json_response(error=error)
Пример #13
0
 def delete(self, request):
     form, error = JsonParser(Argument('id', type=int,
                                       help='请指定操作对象')).parse(request.GET)
     if error is None:
         rel_apps = []
         for app in App.objects.filter(rel_services__isnull=False):
             rel_services = json.loads(app.rel_services)
             if form.id in rel_services:
                 rel_apps.append(app.name)
         if rel_apps:
             return json_response(
                 error=
                 f'该服务在配置中心已被 "{", ".join(rel_apps)}" 依赖,请解除依赖关系后再尝试删除。')
         # auto delete configs
         Config.objects.filter(type='src', o_id=form.id).delete()
         ConfigHistory.objects.filter(type='src', o_id=form.id).delete()
         Service.objects.filter(pk=form.id).delete()
     return json_response(error=error)
Пример #14
0
 def delete(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='请指定操作对象')
     ).parse(request.GET)
     if error is None:
         if Deploy.objects.filter(app_id=form.id).exists():
             return json_response(error='该应用在应用发布中已存在关联的发布配置,请删除相关发布配置后再尝试删除')
         # auto delete configs
         Config.objects.filter(type='app', o_id=form.id).delete()
         ConfigHistory.objects.filter(type='app', o_id=form.id).delete()
         for app in App.objects.filter(rel_apps__isnull=False):
             rel_apps = json.loads(app.rel_apps)
             if form.id in rel_apps:
                 rel_apps.remove(form.id)
                 app.rel_apps = json.dumps(rel_apps)
                 app.save()
         App.objects.filter(pk=form.id).delete()
     return json_response(error=error)
Пример #15
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('name', help='请输入引擎名称'),
         Argument('engine_type',
                  filter=lambda x: x in dict(ExecEngine.ENGINE_TYPES),
                  help='请选择引擎类型'),
         Argument('start_user', help='请输入启动用户', required=False),
         Argument('start_command', help='请输入启动命令', required=False),
         Argument('start_script', help='请输入启动脚本', required=False),
         Argument('engine_desc', required=False)).parse(request.body)
     if error is None:
         if form.id:
             # 更新
             ExecEngine.objects.filter(pk=form.pop('id')).update(**form)
         else:
             ExecEngine.objects.create(**form)
     return json_response(error=error)
Пример #16
0
def ldap_test(request):
    form, error = JsonParser(
        Argument('server'),
        Argument('port', type=int),
        Argument('admin_dn'),
        Argument('password'),
    ).parse(request.body)
    if error is None:
        try:
            con = ldap.initialize("ldap://{0}:{1}".format(
                form.server, form.port),
                                  bytes_mode=False)
            con.simple_bind_s(form.admin_dn, form.password)
            return json_response()
        except Exception as e:
            error = eval(str(e))
            return json_response(error=error['desc'])
    return json_response(error=error)
Пример #17
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='参数错误'),
         Argument('token', help='参数错误'),
         Argument('path', help='参数错误'),
     ).parse(request.POST)
     if error is None:
         file = request.FILES.get('file')
         if not file:
             return json_response(error='请选择要上传的文件')
         host = Host.objects.get(pk=form.id)
         if not host:
             return json_response(error='未找到指定主机')
         cli = host.get_ssh()
         rds_cli = get_redis_connection()
         callback = partial(self._compute_progress, rds_cli, form.token, file.size)
         cli.put_file_by_fl(file, os.path.join(form.path, file.name), callback=callback)
     return json_response(error=error)
Пример #18
0
def parse_text(request):
    form, error = JsonParser(
        Argument('o_id', type=int, help='缺少必要参数'),
        Argument('type', filter=lambda x: x in dict(Config.TYPES), help='缺少必要参数'),
        Argument('env_id', type=int, help='缺少必要参数'),
        Argument('data', handler=str.strip, help='缺少必要参数')
    ).parse(request.body)
    if error is None:
        data = {}
        for line in form.pop('data').split('\n'):
            line = line.strip()
            if line:
                fields = line.split('=', 1)
                if len(fields) != 2 or fields[0].strip() == '':
                    return json_response(error=f'解析配置{line!r}失败,确认其遵循 key = value 格式')
                data[fields[0].strip()] = fields[1].strip()
        _parse(request, form, data)
    return json_response(error=error)
Пример #19
0
 def post(self, request):
     form, error = JsonParser(
         Argument('o_id', type=int, help='缺少必要参数'),
         Argument('type', filter=lambda x: x in dict(Config.TYPES), help='缺少必要参数'),
         Argument('envs', type=list, filter=lambda x: len(x), help='请选择环境'),
         Argument('key', help='请输入Key'),
         Argument('is_public', type=bool, help='缺少必要参数'),
         Argument('value', type=str, default=''),
         Argument('desc', required=False)
     ).parse(request.body)
     if error is None:
         form.value = form.value.strip()
         form.updated_at = human_datetime()
         form.updated_by = request.user
         envs = form.pop('envs')
         for env_id in envs:
             Config.objects.create(env_id=env_id, **form)
             ConfigHistory.objects.create(action='1', env_id=env_id, **form)
     return json_response(error=error)
Пример #20
0
 def delete(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='参数错误')
     ).parse(request.GET)
     if error is None:
         group = Group.objects.filter(pk=form.id).first()
         if not group:
             return json_response(error='未找到指定分组')
         if Group.objects.filter(parent_id=group.id).exists():
             return json_response(error='请移除子分组后再尝试删除')
         if group.hosts.exists():
             return json_response(error='请移除分组下的主机后再尝试删除')
         if not Group.objects.exclude(pk=form.id).exists():
             return json_response(error='请至少保留一个分组')
         role = Role.objects.filter(group_perms__regex=fr'[^0-9]{form.id}[^0-9]').first()
         if role:
             return json_response(error=f'账户角色【{role.name}】的主机权限关联该分组,请解除关联后再尝试删除')
         group.delete()
     return json_response(error=error)
Пример #21
0
def email_test(request):
    form, error = JsonParser(
        Argument('server', help='请输入邮件服务地址'),
        Argument('port', type=int, help='请输入邮件服务端口号'),
        Argument('username', help='请输入邮箱账号'),
        Argument('password', help='请输入密码/授权码'),
    ).parse(request.body)
    if error is None:
        try:
            if form.port == 465:
                server = smtplib.SMTP_SSL(form.server, form.port)
            else:
                server = smtplib.SMTP(form.server, form.port)
            server.login(form.username, form.password)
            return json_response()
        except Exception as e:
            error = e.smtp_error.decode('utf-8')
            return json_response(error=error)
    return json_response(error=error)
Пример #22
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('name', help='请输入任务名称'),
         Argument('addr', help='请输入监控地址'),
         Argument('type',
                  filter=lambda x: x in dict(Detection.TYPES),
                  help='请选择监控类型'),
         Argument('extra', required=False),
         Argument('desc', required=False),
         Argument('rate', type=int, default=5),
         Argument('threshold', type=int, default=3),
         Argument('quiet', type=int, default=24 * 60),
         Argument('notify_grp', type=list, required=False),
         Argument('notify_mode', type=list, required=False),
     ).parse(request.body)
     if error is None:
         add_monitor(request.user, form)
     return json_response(error=error)
Пример #23
0
def do_task(request):
    form, error = JsonParser(
        Argument('host_ids',
                 type=list,
                 filter=lambda x: len(x),
                 help='请选择执行主机'),
        Argument('command', help='请输入执行命令内容')).parse(request.body)
    if error is None:
        if not request.user.has_host_perm(form.host_ids):
            return json_response(error='无权访问主机,请联系管理员')
        token = Channel.get_token()
        for host in Host.objects.filter(id__in=form.host_ids):
            Channel.send_ssh_executor(token=token,
                                      hostname=host.hostname,
                                      port=host.port,
                                      username=host.username,
                                      command=form.command)
        return json_response(token)
    return json_response(error=error)
Пример #24
0
 def post(self, request):
     form, error = JsonParser(Argument('id', type=int, required=False),
                              Argument('name', help='请输入环境名称'),
                              Argument('key', help='请输入唯一标识符'),
                              Argument('desc',
                                       required=False)).parse(request.body)
     if error is None:
         form.key = form.key.replace("'", '')
         env = Environment.objects.filter(key=form.key).first()
         if env and env.id != form.id:
             return json_response(error=f'唯一标识符 {form.key} 已存在,请更改后重试')
         if form.id:
             Environment.objects.filter(pk=form.id).update(**form)
         else:
             env = Environment.objects.create(created_by=request.user,
                                              **form)
             if request.user.role:
                 request.user.role.add_deploy_perm('envs', env.id)
     return json_response(error=error)
Пример #25
0
 def patch(self, request):
     form, error = JsonParser(
         Argument('id', type=int, help='请指定操作对象'),
         Argument('username', required=False),
         Argument('password', required=False),
         Argument('nickname', required=False),
         Argument('role_id', required=False),
         Argument('is_active', type=bool, required=False),
     ).parse(request.body, True)
     if error is None:
         if form.get('password'):
             form.token_expired = 0
             form.password_hash = User.make_password(form.pop('password'))
         if User.objects.filter(
                 username=form.username,
                 deleted_by_id__isnull=True).exclude(id=form.id).exists():
             return json_response(error=f'已存在登录名为【{form.username}】的用户')
         User.objects.filter(pk=form.pop('id')).update(**form)
     return json_response(error=error)
Пример #26
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('name', help='请输入模版名称'),
         Argument('type', help='请选择模版类型'),
         Argument('body', help='请输入模版内容'),
         Argument('interpreter', default='sh'),
         Argument('host_ids', type=list, handler=json.dumps, default=[]),
         Argument('desc', required=False)
     ).parse(request.body)
     if error is None:
         if form.id:
             form.updated_at = human_datetime()
             form.updated_by = request.user
             ExecTemplate.objects.filter(pk=form.pop('id')).update(**form)
         else:
             form.created_by = request.user
             ExecTemplate.objects.create(**form)
     return json_response(error=error)
Пример #27
0
def login(request):
    form, error = JsonParser(Argument('username', help='请输入用户名'),
                             Argument('password',
                                      help='请输入密码')).parse(request.body)
    if error is None:
        user = User.objects.filter(username=form.username).first()
        if user:
            if not user.is_active:
                return json_response(error="账户已被禁用")
            if user.verify_password(form.password):
                cache.delete(form.username)
                x_real_ip = request.headers.get('x-real-ip', '')
                token_isvalid = user.access_token and len(
                    user.access_token
                ) == 32 and user.token_expired >= time.time()
                user.access_token = user.access_token if token_isvalid else uuid.uuid4(
                ).hex
                user.token_expired = time.time() + 8 * 60 * 60
                user.last_login = human_datetime()
                user.last_ip = x_real_ip
                user.save()
                return json_response({
                    'access_token':
                    user.access_token,
                    'nickname':
                    user.nickname,
                    'is_supper':
                    user.is_supper,
                    'has_real_ip':
                    True if x_real_ip else False,
                    'permissions': [] if user.is_supper else user.page_perms
                })

        value = cache.get_or_set(form.username, 0, 86400)
        if value >= 3:
            if user and user.is_active:
                user.is_active = False
                user.save()
            return json_response(error='账户已被禁用')
        cache.set(form.username, value + 1, 86400)
        return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用")
    return json_response(error=error)
Пример #28
0
 def post(self, request):
     form, error = JsonParser(
         Argument('enable', type=bool, help='参数错误'),
         Argument('code', required=False)
     ).parse(request.body)
     if error is None:
         if form.enable:
             if not form.code:
                 return json_response(error='请输入验证码')
             key = f'{request.user.username}:code'
             code = cache.get(key)
             if not code:
                 return json_response(error='验证码已失效,请重新获取')
             if code != form.code:
                 ttl = cache.ttl(key)
                 cache.expire(key, ttl - 100)
                 return json_response(error='验证码错误')
             cache.delete(key)
         AppSetting.set('MFA', {'enable': form.enable})
     return json_response(error=error)
Пример #29
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('title', help='请输入导航标题'),
         Argument('desc', help='请输入导航描述'),
         Argument('logo', help='请上传导航logo'),
         Argument('links',
                  type=list,
                  filter=lambda x: len(x),
                  help='请设置导航链接'),
     ).parse(request.body)
     if error is None:
         form.links = json.dumps(form.links)
         if form.id:
             Navigation.objects.filter(pk=form.id).update(**form)
         else:
             nav = Navigation.objects.create(**form)
             nav.sort_id = nav.id
             nav.save()
     return json_response(error=error)
Пример #30
0
 def patch(self, request):
     form, error = JsonParser(
         Argument('old_password', required=False),
         Argument('new_password', required=False),
         Argument('nickname', required=False),
     ).parse(request.body, True)
     if error is None:
         if form.get('old_password') and form.get('new_password'):
             if len(form.new_password) < 6:
                 return json_response(error='请设置至少6位的新密码')
             if request.user.verify_password(form.old_password):
                 request.user.password_hash = User.make_password(
                     form.new_password)
                 request.user.token_expired = 0
                 request.user.save()
             else:
                 return json_response(error='原密码错误,请重新输入')
         if form.get('nickname'):
             request.user.nickname = form.nickname
             request.user.save()
     return json_response(error=error)