Compare commits

...

1217 Commits

Author SHA1 Message Date
Jiangjie.Bai
ca3c56320e fix: 锁定依赖包版本 pyOpenSSL==22.0.0 2022-09-27 15:47:47 +08:00
Aaron3S
2ed2c16ff5 fix: 修改解密异常抛出范围 2022-09-27 15:47:03 +08:00
Aaron3S
3069bb5b0c fix: 修复空字符串加密报错的问题 2022-09-27 11:28:31 +08:00
Aaron3S
b0650b0047 perf: 优化去除结尾空字节的写法 2022-09-26 15:29:28 +08:00
Aaron3S
7e133bb0c4 feat: 增加PIICO设备配置项 2022-09-26 14:39:53 +08:00
Aaron3S
bd854cfd0f feat: 增加国密配置项 2022-09-26 14:39:53 +08:00
Aaron3S
f458eff527 fix: 修复密码后空格的问题 2022-09-26 14:38:45 +08:00
feng626
97b37bfb5d fix: reset ssh url problem 2022-09-21 18:34:47 +08:00
吴小白
4d7ff0828b fix: 修复 redis 异常后 celery 旧任务不执行的问题 2022-09-21 18:34:00 +08:00
ibuler
7db3d63e64 fix: 修复 celery 丢失心跳不会重连的问题 2022-09-21 18:34:00 +08:00
Jiangjie.Bai
fa08517bea Merge pull request #8868 from jumpserver/dev
v2.26.0-rc4
2022-09-15 16:16:51 +08:00
Jiangjie.Bai
f86d045c01 fix: 更新翻译 2022-09-15 16:12:12 +08:00
吴小白
1a7fd58abf perf: 修复容器重启页面报错 2022-09-15 15:05:01 +08:00
Jiangjie.Bai
d808256e6a Merge pull request #8864 from jumpserver/dev
v2.26.0-rc3
2022-09-14 20:44:13 +08:00
jiangweidong
305a1b10ed feat: 补充翻译 2022-09-14 20:43:21 +08:00
fit2bot
8c277e8875 fix: 修复mfa失效日期 失效问题 (#8862)
Co-authored-by: feng626 <1304903146@qq.com>
2022-09-14 16:17:51 +08:00
Jiangjie.Bai
061b60ef59 Merge pull request #8858 from jumpserver/dev
v2.26.0-rc2
2022-09-13 17:40:13 +08:00
fit2bot
c008115888 fix: 修复配置mfa失效日期 失效问题 (#8856)
Co-authored-by: feng626 <1304903146@qq.com>
2022-09-13 17:39:09 +08:00
feng626
8d1fb84aaf perf: 工单新增相关过滤 2022-09-13 17:39:09 +08:00
jiangweidong
43d61b5348 feat: 支持对开启SSL/TLS的MongoDb数据库改密 2022-09-13 17:39:09 +08:00
ibuler
c26a786287 perf: 优化加密,没有rsa则不加密 2022-09-13 17:39:09 +08:00
fit2bot
cb2bd0cf2c fix: 修复账号备份失败问题 (#8852)
Co-authored-by: feng626 <1304903146@qq.com>
2022-09-13 17:39:09 +08:00
jiangweidong
3048e6311b fix: 修复华为短信配置错误,前端提示不对的问题 2022-09-13 17:39:09 +08:00
fit2bot
5e16b6387a fix: 修复配置mfa失效日期 失效问题 (#8856)
Co-authored-by: feng626 <1304903146@qq.com>
2022-09-13 17:20:09 +08:00
feng626
93e1adf376 perf: 工单新增相关过滤 2022-09-13 15:28:46 +08:00
jiangweidong
556bd3682e feat: 支持对开启SSL/TLS的MongoDb数据库改密 2022-09-13 15:27:54 +08:00
ibuler
6bbbe312a2 perf: 优化加密,没有rsa则不加密 2022-09-13 15:27:20 +08:00
fit2bot
1ac64db0ba fix: 修复账号备份失败问题 (#8852)
Co-authored-by: feng626 <1304903146@qq.com>
2022-09-09 16:01:08 +08:00
jiangweidong
fa54a98d6c fix: 修复华为短信配置错误,前端提示不对的问题 2022-09-08 18:55:01 +08:00
Jiangjie.Bai
31de9375e7 Merge pull request #8846 from jumpserver/dev
v2.26.0-rc1
2022-09-08 15:43:18 +08:00
halo
697270e3e6 perf: 优化清理任务偶发错误 2022-09-08 15:40:23 +08:00
halo
56c324b04e perf: utf-8编码忽略报错 2022-09-07 17:50:34 +08:00
jiangweidong
984b94c874 perf: 修改数据库应用ssl相关字段名 (#8840)
* 修改变量名

* 修改变量名
2022-09-07 16:08:37 +08:00
jiangweidong
50df7f1304 perf: 支持连接开启ssl且自签证书的db时 2022-09-07 11:23:18 +08:00
jiangweidong
8e5833aef0 修改一下顺序 2022-09-06 15:49:36 +08:00
jiangweidong
f20b465ddf feat: 改密计划支持MongoDB改密 2022-09-06 15:49:36 +08:00
jiangweidong
409d254a2e feat: 支持MFA可配置华为云平台短信对接 2022-09-06 15:48:33 +08:00
halo
e6d30fa77d perf: telnet系统工具输出使用utf-8编码 2022-09-06 14:59:16 +08:00
jiangweidong
b25404cac1 feat: 支持OAuth2协议自定义注销功能 2022-09-06 14:58:48 +08:00
feng626
ef4cc5f646 perf: 优化账号备份 2022-09-06 14:40:59 +08:00
Jiangjie.Bai
f0dc519423 perf: 优化 windows ad帮助链接地址 2022-08-25 15:24:33 +08:00
老广
2cb6da3129 Merge pull request #8811 from jumpserver/pr@dev@perf_customauth
perf: 优化 custom 认证模块加载逻辑,判断MD5值,启动时只加载一次
2022-08-25 15:23:08 +08:00
Jiangjie.Bai
1819083a25 perf: 优化 custom 认证模块加载逻辑,判断MD5值,启动时只加载一次 2022-08-25 15:04:45 +08:00
老广
bdeec0d3cb Merge pull request #8803 from jumpserver/pr@dev@feat_customauthbackend
feat: 支持自定义认证 backend;统一其他认证方式的信号触发逻辑;
2022-08-24 18:44:05 +08:00
Jiangjie.Bai
8fc5c4cf9e feat: 支持自定义认证 backend;统一其他认证方式的信号触发逻辑;通过配置文件控制 2022-08-24 18:41:47 +08:00
Jiangjie.Bai
89051b2c67 feat: 支持自定义认证 backend;统一其他认证方式的信号触发逻辑; 2022-08-24 18:04:22 +08:00
Jiangjie.Bai
9123839b48 feat: 支持自定义认证 backend;统一其他认证方式的信号触发逻辑; 2022-08-24 17:38:17 +08:00
老广
258c8a30d1 Merge pull request #8800 from jumpserver/pr@dev@feat_support_piico_gm
feat: 支持 piico 设备国密加密
2022-08-24 14:58:24 +08:00
jiangweidong
af75b5269c ca_cert不做大小限制 2022-08-24 14:51:38 +08:00
jiangweidong
0a66693a41 feat: MongoDB支持连接SSL类型 2022-08-24 14:51:38 +08:00
Jiangjie.Bai
7151201d58 feat: 支持自定义认证 backend;统一其他认证方式的信号触发逻辑; 2022-08-24 11:41:48 +08:00
Aaron3S
51820f23bf perf: 优化代码表达 2022-08-23 20:19:53 +08:00
Aaron3S
8772cd8c71 feat: 支持 piico 设备国密加密 2022-08-23 17:40:01 +08:00
ibuler
60cb1f8136 fix: 修复默认 gcm key padding 2022-08-22 14:26:11 +08:00
吴小白
5f1b7ff8f9 fix: 修正任务报错 2022-08-22 14:12:11 +08:00
feng626
37b150bc04 fix: 表单提交csrftoken问题 2022-08-19 17:22:59 +08:00
吴小白
1432fe1609 fix: 添加 openssh-client 依赖包 2022-08-19 17:13:56 +08:00
Jiangjie.Bai
8ae98887ee Revert "fix: 修复服务端渲染请求缺少csrf token 问题" (#8780)
This reverts commit 24a1738e73.
2022-08-19 14:19:47 +08:00
feng626
24a1738e73 fix: 修复服务端渲染请求缺少csrf token 问题 2022-08-19 10:52:59 +08:00
Jiangjie.Bai
188c04c9a6 Merge pull request #8776 from jumpserver/dev
v2.25.0
2022-08-18 16:12:16 +08:00
吴小白
bb4da12366 perf: 更新 pypi 镜像 2022-08-18 12:10:41 +08:00
fit2bot
382112ee33 perf: 批量命令搜索优化 (#8772)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-18 11:48:58 +08:00
fit2bot
3e69e6840b fix: oauth2不属于密码认证 (#8771)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-18 10:30:20 +08:00
Jiangjie.Bai
a82ed3e924 Merge pull request #8768 from jumpserver/dev
v2.25.0-rc5
2022-08-17 18:57:22 +08:00
fit2bot
b347acd5ec perf: 替换 mirrors (#8765)
* perf: 替换 mirrors

* perf: 使用中科大 mirrors

Co-authored-by: 吴小白 <296015668@qq.com>
2022-08-17 18:50:47 +08:00
Jiangjie.Bai
ccd6b01020 fix: 修复开启仅允许已存在用户登录并且是第三方用户认证时报错instance没有id的问题 2022-08-17 18:47:36 +08:00
Jiangjie.Bai
831b67eae4 Merge pull request #8763 from jumpserver/dev
v2.25.0-rc4
2022-08-17 16:52:28 +08:00
Jiangjie.Bai
3ab634d88e fix: 翻译 2022-08-17 16:43:47 +08:00
Jiangjie.Bai
867ad94a30 fix: 修改认证重定向地址 scheme 取值逻辑 2022-08-17 15:23:35 +08:00
fit2bot
7d0a19635a fix: 修复登录符合拒绝时 登录日志类型异常问题 (#8758)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-17 14:45:02 +08:00
Jiangjie.Bai
4642804077 Merge pull request #8756 from jumpserver/dev
v2.25.0-rc3
2022-08-16 19:07:42 +08:00
fit2bot
d405bae205 fix: 修复认证失败后错误信息总是 IP block 的问题 (#8755)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-08-16 17:46:17 +08:00
fit2bot
68841d1f15 fix: 配置仅已存在用户登录后 cas用户首次登录报403 (#8752)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-16 17:24:58 +08:00
fit2bot
4cad5affec fix: 修复工单火狐浏览器上页面展示 (#8753)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-16 17:15:21 +08:00
fit2bot
2f8a07e665 perf: 批量命令新增过滤选项 (#8749)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-16 13:56:19 +08:00
fit2bot
78133b0c60 fix: 修复后台手机号校验 (#8747)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-15 17:39:54 +08:00
Jiangjie.Bai
88d9078c43 fix: 修改 OAuth2.0 认证的字段的必填项 2022-08-15 16:56:34 +08:00
fit2bot
5559f112db fix: 用户登录复合500 (#8743)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-15 16:21:27 +08:00
Jiangjie.Bai
9a4b32cb3c perf: 优化 metadata 类型添加 float 2022-08-15 16:08:56 +08:00
feng626
ddf4b61c9f fix: 修复全局组织批量删除资产500 2022-08-15 16:08:23 +08:00
feng626
0eaaa7b4f6 fix: 用户异地登陆bug 2022-08-15 10:45:22 +08:00
Jiangjie.Bai
09160fed5d Merge pull request #8740 from jumpserver/dev
v2.25.0-rc2
2022-08-12 18:05:13 +08:00
fit2bot
18af5e8c4a fix: 【登录日志】登录复核用户被拒绝,登录日志无登录日志记录】 (#8739)
* fix: 【登录】第三方用户登录复核,拒绝状态,未真正拦截

* fix: 【登录日志】登录复核用户被拒绝,登录日志无登录日志记录】

* fix: 【登录日志】用户设置登录复核,登录。此时不处理工单,管理员全局组织下查看登录日志,日志无限新增,且无记录用户名】

Co-authored-by: huangzhiwen <zhiwen.huang@fit2cloud.com>
2022-08-12 18:01:04 +08:00
fit2bot
1ed388459b fix: 工单流 全局组织不能更新 (#8735)
Co-authored-by: feng626 <1304903146@qq.com>
2022-08-12 14:29:13 +08:00
feng626
2e944c6898 perf: 修改下载版本号 2022-08-11 16:25:32 +08:00
Jiangjie.Bai
8409523fee Merge pull request #8728 from jumpserver/dev
v2.25.0-rc1
2022-08-11 14:12:23 +08:00
吴小白
16634907b4 perf: ldap 支持客户端证书认证 2022-08-11 14:09:57 +08:00
feng626
cfa5de13ab feat: 节点树搜索 2022-08-11 14:08:45 +08:00
feng626
28c8ec1fab feat: 添加app 获取对应actions接口 2022-08-10 19:34:29 +08:00
huangzhiwen
a14ebc5f0f fix: 解决第三方登录无限重定向问题 2022-08-10 19:32:39 +08:00
Jiangjie.Bai
6af20d298d perf: 修改翻译 2022-08-10 19:07:22 +08:00
Jiangjie.Bai
795d6e01dc fix: 修改测试IP地址工具的默认超市时间为 0.5s 2022-08-10 19:07:22 +08:00
Eric
acf8b5798b perf: 优化rdp文件名的显示 2022-08-10 18:41:38 +08:00
jiangweidong
abcd12f645 perf: 补充cmpp2翻译及部分报错提示 (#8717)
* 修改CMPPv2.0翻译内容

* perf: 捕捉连接网关出错问题

* perf: 测试短信验证失败提示错误信息

* perf: 修改翻译
2022-08-10 17:32:28 +08:00
fit2bot
30fe5214c7 fix: 增加上了第三方用户登录失败的原因 (#8714)
* feat: OAuth2.0登录方式加上用户登录规则校验

* fix: 修复第三方用户登录规则(复核)问题

* fix: 增加上了第三方用户登录失败的原因

* fix: 修改变量名称

Co-authored-by: huangzhiwen <zhiwen.huang@fit2cloud.com>
2022-08-10 11:03:51 +08:00
jiangweidong
708a87c903 feat: 支持CMPPv2.0协议短信网关 (#8591)
* feat: 支持CMPPv2.0协议短信网关

* 修改翻译

Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-08-09 16:09:20 +08:00
huangzhiwen
6a30e0739d feat: OAuth2.0登录方式加上用户登录规则校验 2022-08-09 11:38:59 +08:00
fit2bot
3951b8b080 fix(auth): 第三方用户(saml2)登录规则设置无效 (#8648)
* fix: 修复 OpenID、CAS、SAML2登录规则设置无效

* refactor: auth_third_party_required写到一个地方和优化代码结构

* refactor: 优化代码结构

* refactor: 修改变量名称

Co-authored-by: huangzhiwen <zhiwen.huang@fit2cloud.com>
2022-08-09 11:24:28 +08:00
Jiangjie.Bai
c295f1451a fix: 修复登录失败日志的原因信息 2022-08-08 15:49:03 +08:00
Jiangjie.Bai
c4a94876cc fix: 增加配置项 SECURE_PROXY_SSL_HEADER request build url 时获取对应的 scheme 2022-08-08 15:00:26 +08:00
feng626
dcab934d9f fix: 修复用户自动登录bug 2022-08-08 11:42:45 +08:00
fit2bot
4ecb0b760f perf: 支持配置文件加密 (#8699)
* crypto

* perf: 暂存一下

* perf: 支持配置文件加密

* perf: 修改位置

* perf: 优化拆分出去

* stash

* perf: js 强制 key 最大 16

* pref: 修改语法

* fix: 修复启用 gm 后,又关闭导致的用户无法登录

Co-authored-by: ibuler <ibuler@qq.com>
2022-08-05 14:53:23 +08:00
fit2bot
b27b02eb9d feat: Cloud 支持局域网 IP 扫描 (#8589)
* feat: Cloud 支持局域网 IP 扫描

* feat: Cloud 支持局域网 IP 扫描

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-08-05 14:45:25 +08:00
Jiangjie.Bai
70cf847cd9 perf: update readme 2022-08-04 18:33:14 +08:00
jiangweidong
2099baaaff feat: 认证方式支持OAuth2.0协议 (#8686)
* feat: 认证方式支持OAuth2.0协议

* perf: 优化 OAuth2 认证逻辑和Logo (对接 Github)

* perf: 优化 OAuth2 认证逻辑和Logo,支持上传图标

* perf: 优化 OAuth2 认证逻辑和Logo,支持上传图标

* perf: 优化 OAuth2 认证逻辑和Logo,支持上传图标

* perf: 优化 OAuth2 认证逻辑和Logo,支持上传图标

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-08-04 14:40:33 +08:00
ibuler
b22aed0cc3 feat: 用户密码 hash 采用 gmsm3 2022-08-03 15:05:22 +08:00
“huailei000”
3e7f83d44e fix:修复忘记密码页布局错位问题 2022-08-02 16:42:55 +08:00
Jiangjie.Bai
40f8b99242 fix: 修复更新资产账号不成功的问题(末尾:) 2022-08-02 16:42:25 +08:00
Jiangjie.Bai
9ff345747b fix: 修复系统平台不能导入的问题 2022-08-02 14:55:32 +08:00
Jiangjie.Bai
9319c4748c perf: 修改用户登录 ACL 翻译信息 2022-08-02 14:54:09 +08:00
老广
e8b4ee5c40 Update README.md 2022-07-29 14:24:08 +08:00
fit2bot
429e838973 perf: 优化用户登录ACL根据规则优先级进行匹配 (#8672)
* perf: 优化用户登录ACL根据规则优先级进行匹配

* perf: 修改冲突

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-07-29 11:37:16 +08:00
fit2bot
ee1aff243c feat: 新增ping、telnet系统工具 (#8666)
* feat: 新增ping、telnet系统工具

* perf: 消息返回

Co-authored-by: halo <wuyihuangw@gmail.com>
2022-07-29 10:02:23 +08:00
fit2bot
ea7133dea0 fix: translate (#8664)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-28 13:47:32 +08:00
jiangweidong
e7229963bf perf: 更换oracle依赖包 2022-07-27 13:42:14 +08:00
feng626
0f7b41d177 fix: super ticket close bug 2022-07-26 18:34:35 +08:00
fit2bot
c4146744e5 perf: 优化授权过期提醒 (#8654)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-25 14:02:07 +08:00
fit2bot
dc32224294 feat: 应用工单支持选择动作 (#8651)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-22 16:24:57 +08:00
fit2bot
d07a230ba6 feat: 添加默认工单授权时间 (#8649)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-22 15:23:16 +08:00
Jiangjie.Bai
f52a0ce960 Merge pull request #8645 from jumpserver/dev
v2.24.0
2022-07-21 15:40:57 +08:00
ibuler
9d17f27fb3 fix: 修复密码可能解密失败报错 2022-07-21 15:37:32 +08:00
feng626
36d0b8d085 fix: 组件角色绑定错误 2022-07-21 15:37:06 +08:00
fit2bot
046356728a perf: sso token 最小60秒 (#8642)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-21 13:51:15 +08:00
Jiangjie.Bai
d34c4fb7ec Merge pull request #8640 from jumpserver/dev
v2.24.0-rc5
2022-07-20 19:07:18 +08:00
Jiangjie.Bai
ca49029d8f fix: 锁定依赖 keystoneauth1==3.4.0 2022-07-20 17:22:22 +08:00
ibuler
12036f8c96 perf: 修改 django 版本 2022-07-20 17:01:06 +08:00
Jiangjie.Bai
60e455bea2 fix: 修改theme_info默认值为{} 2022-07-20 16:13:20 +08:00
fit2bot
e7dd731139 fix: 授权过期url 404 -> /console/ (#8634)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-20 15:44:00 +08:00
Jiangjie.Bai
88ae8ac67a fix: 会话列表修改翻译为终端ID 2022-07-20 13:54:43 +08:00
feng626
626b6da9c4 fix cmd为空时bug 2022-07-20 13:43:04 +08:00
fit2bot
cb8690dd63 fix: 处理组件获取connection token获取不到的问题 (#8629)
* fix: 处理组件获取connection token获取不到的问题

* fix: ViewSet 显示获取资源用户

* fix: ViewSet 显示获取资源用户

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-07-20 13:23:43 +08:00
ibuler
2b2aa8f072 perf: 优化 换行 2022-07-20 13:19:39 +08:00
ibuler
772e540527 perf: 修改 connect token 换行 2022-07-20 13:19:39 +08:00
ibuler
ca5f6f3c6f perf: 修改 windows ansible shell 2022-07-20 13:17:45 +08:00
Jiangjie.Bai
29656b1630 fix: 修改获取 rdp-file / client-url / smart-endpoint 时endpoint host后台处理为当前请求的host 2022-07-19 19:05:15 +08:00
吴小白
bdf59da0f6 Merge pull request #8625 from jumpserver/pr@dev@fix_perms_asset-user-permission
fix: 管理员与用户资产列表排序不统一
2022-07-19 18:06:40 +08:00
Jiangjie.Bai
7b6eeb2e3d fix: 清除 ftp 日志 2022-07-19 17:57:09 +08:00
huangzhiwen
fed0732c1e fix: 管理员与用户资产列表排序不统一 2022-07-19 17:28:10 +08:00
Jiangjie.Bai
c12efffcc9 Merge pull request #8622 from jumpserver/dev
v2.24.0-rc4
2022-07-19 16:25:32 +08:00
feng626
358460e7f0 fix: 如配置SECURITY_VIEW_AUTH_NEED_MFA 跳过校验 2022-07-19 16:24:55 +08:00
Jiangjie.Bai
6319be0ea3 Merge pull request #8620 from jumpserver/dev
v2.24.0-rc4
2022-07-19 16:12:08 +08:00
fit2bot
cc2b858769 fix: 修复获取令牌信息的remote app资产信息 (#8619)
* fix: 修复连接令牌只获取自己的令牌信息;修复连接令牌系统用户角色权限问题(普通用户看不到);

* fix: 修复获取令牌信息的remote app资产信息

* fix: 修复获取用户个人信息时使用连接令牌

* fix: 修复获取profile时的连接令牌问题

* fix: 修复连接令牌问题

* fix: 修复连接令牌问题

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-07-19 15:57:02 +08:00
fit2bot
585ddeb25b fix: 授权过期天数修改 (#8618)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-19 11:15:56 +08:00
fit2bot
0eab83f73b fix: 修改翻译 (#8616)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-19 10:49:15 +08:00
fit2bot
62d403bf21 fix: reverse console (#8615)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-18 19:24:17 +08:00
ibuler
bb9d32dc18 perf: 修改所有组织名称 2022-07-18 14:31:50 +08:00
fit2bot
e09383ecf4 fix: django 3.1.14 (#8613)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-18 13:24:31 +08:00
Jiangjie.Bai
4d7f8ffc71 Merge pull request #8610 from jumpserver/dev
v2.24.0-rc3
2022-07-18 12:02:23 +08:00
fit2bot
af5295d30e fix: django 还原 (#8609)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-18 11:53:47 +08:00
feng626
5055d140fd fix: 修复host为空情况 2022-07-18 11:32:38 +08:00
Eric
2ca72a4bff fix: 修复未选择用户,无法创建共享会话的问题 2022-07-18 11:32:06 +08:00
Eric
de61e780e3 fix: 修复错误提示的翻译问题 2022-07-18 11:31:02 +08:00
halo
e1b3851be3 perf: 优化资产节点搜索,查询全路径 2022-07-17 14:18:20 +08:00
Jiangjie.Bai
c665b0dbae Merge pull request #8603 from jumpserver/dev
v2.24.0-rc2
2022-07-15 18:07:09 +08:00
huangzhiwen
0eaca0c1cb fix: 解决mac m1 pip install pymssql报错问题 2022-07-15 18:06:34 +08:00
fit2cloud
8824b6b54e fix: 解决pip不能安装psycopg2-binary和pymssql问题 2022-07-15 18:06:34 +08:00
fit2bot
4fd82b9946 fix: 修改翻译 (#8602)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-15 17:17:56 +08:00
feng626
1b1b70e7bd fix: 处理应用账号脏数据 2022-07-15 17:03:26 +08:00
Jiangjie.Bai
41541a91b9 fix: 修复 public 和 smart API 权限包含 connection token 2022-07-15 15:01:20 +08:00
fit2bot
93537c07a1 fix: 修复工单授权组织问题 (#8599)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-15 11:38:50 +08:00
Jiangjie.Bai
a770a19252 Merge pull request #8595 from jumpserver/dev
v2.24.0-rc1
2022-07-14 17:44:33 +08:00
Jiangjie.Bai
395636296d fix: 修改连接token secret长度为16 2022-07-14 17:43:57 +08:00
fit2bot
9967d52416 perf: 暂时去掉历史账号权限 (#8594)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-14 15:37:00 +08:00
Jiangjie.Bai
717f97cd88 Merge pull request #8592 from jumpserver/dev
v2.24.0-rc1
2022-07-14 14:40:03 +08:00
Jiangjie.Bai
dec8e3459a feat: 添加 Oracle 数据库 version 迁移文件默认 12c 版本
feat: 添加 Oracle 数据库 version 迁移文件默认 12c 版本
2022-07-14 11:18:26 +08:00
fit2bot
4a3d7a8524 perf: history account model queryset (#8588)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-13 17:13:02 +08:00
fit2bot
f758414844 fix: 审批时 来着不同组织的资产校验 (#8586)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-13 16:54:44 +08:00
dependabot[bot]
af080fe38d build(deps): bump django from 3.2.13 to 3.2.14 in /requirements
Bumps [django](https://github.com/django/django) from 3.2.13 to 3.2.14.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.13...3.2.14)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-13 16:51:22 +08:00
ibuler
f0fbc73f73 perf: 工作台支持 root 2022-07-13 16:31:35 +08:00
fit2bot
ce2f6fdc84 feat: Endpoint 支持 oracle 版本 (#8585)
* feat: Endpoint 支持 oracle 版本

* feat: Endpoint 支持 oracle 版本

* feat: Endpoint 支持 oracle 版本

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-07-13 16:29:05 +08:00
fit2bot
2abca39597 fix: ticket bug (#8584)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-13 15:48:55 +08:00
fit2bot
11e538d417 fix: 工单三方审批不支持修改资产 (#8582)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-13 11:31:53 +08:00
fit2bot
5155b3c184 fix: 修复bluk_create root 组织下判断 (#8581)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-13 11:00:12 +08:00
feng626
e724cdf53d fix: OrgManager add bulk_create method 2022-07-13 10:47:12 +08:00
halo
191d37dd56 feat: 支持session存储方式可配置,可选cache或db 2022-07-13 10:21:20 +08:00
Jiangjie.Bai
602192696c feat: 添加翻译信息 2022-07-12 18:31:18 +08:00
Jiangjie.Bai
b262643f0a fix: 连接令牌添加 expire_time 和 is_valid 字段 2022-07-12 18:29:48 +08:00
fit2bot
cd119a2999 fix: 飞书登录登录日志不记录认证方式 (#8574)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-12 17:36:40 +08:00
fit2bot
d789810984 fix: condirm (#8572)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-12 16:02:41 +08:00
fit2bot
b5cfc6831b feat: 工单支持审批时修改资产 (#8549)
Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2022-07-12 15:28:42 +08:00
Jiangjie.Bai
b64727e04c fix: 修改用户自更新失败的问题 2022-07-12 14:22:07 +08:00
fit2bot
c7c0374c78 perf: 修改主题 (#8569)
* perf: 优化登录 backend

* perf: 修改主题

Co-authored-by: ibuler <ibuler@qq.com>
2022-07-12 13:45:48 +08:00
Jiangjie.Bai
f3cf071362 feat: 修改connection token secret不显示 2022-07-11 19:37:55 +08:00
fit2bot
27cbbfbc79 refactor: 重构 Connection Token 模块 (完成获取 Super connection token API 逻辑) (#8559)
* refactor: 重构 Connection Token 模块 (完成 Model 设计和创建 Token 的API逻辑)

* refactor: 重构 Connection Token 模块 (完成获取 Token 详细信息的 API 逻辑)

* refactor: 重构 Connection Token 模块 (完成获取 RDP 文件 API 逻辑)

* refactor: 重构 Connection Token 模块 (完成获取 Client url API 逻辑)

* refactor: 重构 Connection Token 模块 (完成获取 Super connection token API 逻辑)

* refactor: 重构 Connection Token 模块 (完成删除原 Connection token 逻辑)

* refactor: 重构 Connection Token 模块 (完成删除原 Connection)

* refactor: 重构 Connection Token 模块 (完善序列类字段)

* refactor: 重构 Connection Token 模块 (完善expire API)

* refactor: 重构 Connection Token 模块 (完善迁移文件)

* refactor: 重构 Connection Token 模块 (完善翻译文件)

* refactor: 重构 Connection Token 模块 (拆分Connection ViewSet)

* refactor: 重构 Connection Token 模块 (修改翻译)

* refactor: 重构 Connection Token 模块 (优化)

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-07-11 18:09:06 +08:00
feng626
7047e445a3 feat: 下载页面添加离线播放器 2022-07-11 17:21:07 +08:00
fit2bot
06375110b9 fix: 修改mfa check 判断 (#8561)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-11 10:48:01 +08:00
Jiangjie.Bai
0e6dbb3e5d fix: 修复 ES 存储 config 被修改的问题 2022-07-08 11:00:22 +08:00
fit2bot
bf7c05f753 fix: 调整confirm (#8554)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-07 17:07:57 +08:00
Jiangjie.Bai
1b4d389f2b fix: 修复创建共享会话链接时 created_by 字段长度问题 2022-07-07 15:44:07 +08:00
fit2bot
0f11ca9c37 perf: 修改翻译 (#8543)
* perf: 修改翻译

* perf: 优化 flash msg page

* perf: 修改 i18n

* perf: 修改 i18n

Co-authored-by: ibuler <ibuler@qq.com>
2022-07-06 17:26:09 +08:00
ibuler
4537e30e4a perf: 修改颜色 2022-07-05 20:28:42 +08:00
dependabot[bot]
2f71ee71b9 build(deps): bump django from 3.2.12 to 3.2.13 in /requirements
Bumps [django](https://github.com/django/django) from 3.2.12 to 3.2.13.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.12...3.2.13)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-05 20:28:20 +08:00
ibuler
98644eeb61 perf: 修改 logo 2022-07-05 20:07:24 +08:00
fit2bot
001e5d857f pref: debug toolbar 太费时间 先禁用 (#8528)
* perf: 修改主题色

* pref: debug toolbar 太费时间 先禁用

* perf: 修改颜色

* perf: 优化 interface

* perf: 修改 avartar

* perf: css color

Co-authored-by: ibuler <ibuler@qq.com>
2022-07-05 14:43:56 +08:00
Jiangjie.Bai
bbcf992531 feat: 添加 OmniDB Enabled 控制
feat: 添加 OmniDB Enabled 控制
2022-07-05 11:12:37 +08:00
fit2bot
75aacd0da6 fix: 用户登录错误处理bug (#8531)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-05 11:08:35 +08:00
fit2bot
0aad0b7279 feat: 账号历史信息 (#8500)
* feat: 账号历史信息

* del app

Co-authored-by: feng626 <1304903146@qq.com>
2022-07-04 18:54:47 +08:00
fit2bot
8ebcb4b73a fix: translate (#8529)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-04 15:14:59 +08:00
fit2bot
88f60b58dd fix: 修复翻译 (#8527)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-04 14:57:45 +08:00
fit2bot
a6cc8a8b05 perf: 优化confirm接口 (#8451)
* perf: 优化confirm接口

* perf: 修改 校验

* perf: 优化 confirm API 逻辑

* Delete django.po

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2022-07-04 11:29:39 +08:00
halo
ca19e45905 perf: 优化截取方法 2022-07-04 11:00:41 +08:00
halo
c5bf4075e7 perf: 优化截取方法 2022-07-04 11:00:41 +08:00
halo
04ceca1b83 perf: 修复命令表系统用户字段长度问题,截取成64字符 2022-07-04 11:00:41 +08:00
Jiangjie.Bai
90228e69e0 perf: 会话列表显示终端名称;修复启动 warning 问题 2022-07-01 19:21:13 +08:00
Jiangjie.Bai
62a2a74c27 perf: 会话列表显示终端名称;修复启动 warning 问题 2022-07-01 19:21:13 +08:00
fit2bot
927ae43af2 perf: 优化工单 (#8524)
Co-authored-by: feng626 <1304903146@qq.com>
2022-07-01 19:07:55 +08:00
feng626
272f64d743 fix: get_target_ip bug 2022-07-01 14:16:54 +08:00
feng626
af2d927c1f perf: del pandas 2022-06-30 20:20:09 +08:00
Jiangjie.Bai
011e9ffec4 fix: 修复导入导出文件时对于bool类型字段的判断问题 2022-06-30 18:28:07 +08:00
Jiangjie.Bai
8e65975cd7 fix: 修改会话共享可以指定用户的一些问题 2022-06-30 14:22:40 +08:00
fit2bot
9465138faf fix: 修复工单迁移文件 (#8513)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-30 11:44:54 +08:00
fit2bot
081089d636 fix: 修复工单命令复合迁移问题 (#8512)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-30 11:23:53 +08:00
jiangweidong
5d80933e7b feat: 会话分享可设置1、5分钟时限,且可分享给指定人 (#8227)
* perf: 完成会话分享可设置1、5分钟时限,且可分享给指定人

* perf: 完成会话分享可设置1、5分钟时限,且可分享给指定人

* perf: 完成会话分享可设置1、5分钟时限,且可分享给指定人

* feat: 完成会话分享可设置1、5分钟时限,且可分享给指定人
2022-06-30 11:21:26 +08:00
fit2bot
067a90ff9a fix: 修复工单数据库命令复合bug (#8511)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-30 11:17:12 +08:00
Jiangjie.Bai
05826abf9d feat: Endpoint 支持标签匹配
feat: Endpoint 支持标签匹配

feat: Endpoint 支持标签匹配

feat: Endpoint 支持标签匹配

feat: Endpoint 添加帮助信息

feat: Endpoint 添加帮助信息
2022-06-29 18:50:27 +08:00
Jiangjie.Bai
e8363ddff8 perf: 优化 BASE_SITE_URL OIDC 可以为空,实现多个不同端点访问时回调为当前访问的地址 2022-06-29 18:46:05 +08:00
fit2bot
de41747bb2 perf: 添加 debug tool bar (#8504)
* perf: 添加 debug tool bar

* perf: 修改 config name

Co-authored-by: ibuler <ibuler@qq.com>
2022-06-29 14:48:54 +08:00
ibuler
77067f18d5 stash tdsql
pref: 测试完成

perf: 修改支持 tdsql 5.7

revert: 欢迎之前的内容

revert: some

perf: 修改 tdsql

pref: 修改 。
2022-06-28 18:05:20 +08:00
fit2bot
3cbce63c54 perf: 拆分登录 View (#8502)
* perf: 拆分登录 View

* perf: 修改 code

Co-authored-by: ibuler <ibuler@qq.com>
2022-06-28 17:39:13 +08:00
fit2bot
c3c99cc5e8 perf: 优化 redis (#8484)
* perf: 优化 redis

* perf: 优化 redis 时间

* perf: 优化时间

* perf: 修改 ssl

* perf: 修改 ssl

* perf: 修改 ssl name

* perf: 修改名称

Co-authored-by: ibuler <ibuler@qq.com>
2022-06-28 17:23:20 +08:00
fit2bot
b33e376c90 fix: 解决一些工单已知问题 (#8501)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-28 17:19:33 +08:00
ibuler
b619ebf423 perf: 修改 jumpserver 版本号,避免缓存 2022-06-28 10:49:02 +08:00
ibuler
b784d8ba87 fix: 升级依赖库版本,解决生成 key 时的内存泄露 2022-06-27 19:11:43 +08:00
fit2bot
fd7f73a18e fix: 修复工单权限问题 (#8493)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-27 14:02:28 +08:00
fit2bot
8247f24d3f fix: 修复工单bug (#8488)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-27 10:15:29 +08:00
ibuler
3749a0c6a1 perf: 修复 middleware 导致的内存增长 2022-06-25 10:34:18 +08:00
Jiangjie.Bai
fd41fd78cf fix: 修改 private_key 的序列类长度为 16384 2022-06-24 19:24:21 +08:00
ibuler
8c31e8e634 perf: 修改 sdk 版本 2022-06-23 19:18:15 +08:00
feng626
648fabbe03 fix: 修复工单迁移文件 2022-06-23 19:15:57 +08:00
feng626
9388f37c39 fix: ticket bug 2022-06-23 18:35:53 +08:00
feng626
b264db3e7e fix: 修复工单迁移文件 2022-06-23 17:45:34 +08:00
ibuler
dbc5b7bdc3 perf: 升级 tencent sdk 2022-06-23 17:29:12 +08:00
ibuler
ac20bc05ba perf: 优化 css 2022-06-23 15:55:33 +08:00
fit2bot
7e2f81a418 perf: 重构 ticket (#8281)
* perf: 重构 ticket

* perf: 优化 tickets

* perf: 暂存

* perf: 建立 ticket model

* perf: 暂存一下

* perf: 修改 tickets

* perf: 修改 import

* perf: 修改model

* perf: 暂存一波

* perf: 修改...

* del process_map field

* 工单重构

* 资产 应用对接前端

* perf: 修改 ticket

* fix: bug

* 修改迁移文件

* 添加其他api

* 去掉process_map

* perf: 优化去掉 signal

* perf: 修改这里

* 修改一点

* perf: 修改工单

* perf: 修改状态

* perf: 修改工单流转

* step 状态切换

* perf: 修改 ticket open

* perf: 修改流程

* perf: stash it

* 改又改

* stash it

* perf: stash

* stash

* migrate

* perf migrate

* 调整一下

* 修复bug

* 修改一点

* 修改一点

* 优化一波

* perf: ticket migrations

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-23 13:52:28 +08:00
Jiangjie.Bai
2471787277 Merge pull request #8457 from jumpserver/pr@dev@perf_redis
perf: redis AND login page
2022-06-23 10:39:22 +08:00
ibuler
e6abdbdadc perf: 修改 req version 2022-06-22 18:17:57 +08:00
Jiangjie.Bai
5ed65ca2ff fix: 修复post方法调用AuthBook接口时500的问题 2022-06-22 17:11:35 +08:00
ibuler
ba6b1bf692 perf: 修改翻译 2022-06-22 14:30:52 +08:00
ibuler
1aa58e1486 perf: 修改 ignore 2022-06-21 19:25:56 +08:00
ibuler
fa51465485 perf: 修改去掉 导入 certs 2022-06-21 19:23:29 +08:00
ibuler
8f59bb2a48 perf: 优化登陆 2022-06-21 19:06:06 +08:00
ibuler
2366da1485 perf: redis AND login page 2022-06-21 18:43:48 +08:00
ibuler
f1a22575d3 perf: 优化登录页面 2022-06-21 16:18:13 +08:00
ibuler
7c1882bb53 perf: login 2022-06-21 10:08:14 +08:00
ibuler
97baeebb2a perf: 修改 redis scan counter 2022-06-20 19:40:07 +08:00
ibuler
8b819f3779 perf: 优化登录 2022-06-20 19:22:48 +08:00
Jiangjie.Bai
d1420de4c2 fix: 修复es类型的命令存储更新忽略证书字段不成功的问题 2022-06-20 14:47:30 +08:00
ibuler
379c7198da pref: 去掉 django-redis-cache 依赖 2022-06-20 14:11:59 +08:00
Eric
710cd0fb3b fix:修复es日期索引忽略证书的问题 2022-06-20 14:06:56 +08:00
Jiangjie.Bai
3fde31f2e0 fix: 修复工单自定义搜索时500的问题 2022-06-17 15:26:23 +08:00
Jiangjie.Bai
d3355ab0ec Merge pull request #8427 from jumpserver/dev
v2.23.0 rc6
2022-06-16 18:12:44 +08:00
Jiangjie.Bai
81598a5264 perf: 推送系统用户用户名提示信息 2022-06-16 18:04:03 +08:00
feng626
298f6ba41d fix: 修改翻译 2022-06-16 18:03:16 +08:00
feng626
8e43e9ee2b fix: 授权过期通知 2022-06-16 17:52:33 +08:00
Jiangjie.Bai
adc8a8f7d3 fix: 修改翻译 2022-06-16 17:10:21 +08:00
Jiangjie.Bai
1e3da50979 fix: 修复会话加入记录更新失败的问题 2022-06-16 16:50:51 +08:00
Jiangjie.Bai
7ac385d64c Merge pull request #8420 from jumpserver/dev
v2.23.0 rc5
2022-06-16 15:46:40 +08:00
Jiangjie.Bai
2be74c4b84 fix: 修复命令列表模糊搜索报错500的问题
fix: 修复命令列表模糊搜索报错500的问题
2022-06-16 13:45:24 +08:00
feng626
75a72fb182 fix: user confirm bug 2022-06-16 11:31:27 +08:00
Jiangjie.Bai
4c2274b14e fix: 修改翻译 2022-06-16 11:19:26 +08:00
feng626
a024f26768 fix: 授权过期消息提示 2022-06-16 11:19:26 +08:00
Jiangjie.Bai
2898c35970 Merge pull request #8411 from jumpserver/dev
v2.23.0 rc4
2022-06-15 19:38:17 +08:00
Jiangjie.Bai
62f5662bd0 fix: 修复openid用户登录时默认邮件后缀使用配置项 2022-06-15 19:33:26 +08:00
ibuler
0fe221019a pref: 优化没有获取到节点的问题 2022-06-15 19:33:26 +08:00
ibuler
d745314aa1 perf: 优化签名认证 2022-06-15 19:33:26 +08:00
feng626
153fad9ac7 feat: add client linux arm64 version 2022-06-15 19:33:26 +08:00
Jiangjie.Bai
0792c7ec49 fix: 修改推送系统用户提示文案 2022-06-15 19:33:26 +08:00
fit2bot
e617697553 fix: 修复授权过期通知bug (#8404)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-15 19:33:26 +08:00
fit2bot
9dc7da3595 perf: 优化 apt (#8398)
* pref: 修改 oracle lib path

* perf: 优化 apt

Co-authored-by: ibuler <ibuler@qq.com>
2022-06-15 19:33:26 +08:00
Jiangjie.Bai
f7f4d3a42e fix: 过滤系统用户密码过滤ansible不支持的字符 2022-06-15 19:33:26 +08:00
feng626
70fcbfe883 perf: 授权过期通知 2022-06-15 19:33:26 +08:00
Jiangjie.Bai
9e16b79abe fix: 修复openid用户登录时默认邮件后缀使用配置项 2022-06-15 19:32:36 +08:00
ibuler
8c839784fb pref: 优化没有获取到节点的问题 2022-06-15 15:31:33 +08:00
ibuler
10adb4e6b7 perf: 优化签名认证 2022-06-15 15:30:51 +08:00
feng626
75c011f1c5 feat: add client linux arm64 version 2022-06-15 15:30:13 +08:00
Jiangjie.Bai
a882ca0d51 fix: 修改推送系统用户提示文案 2022-06-15 15:20:08 +08:00
fit2bot
e0a2d03f44 fix: 修复授权过期通知bug (#8404)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-15 15:01:56 +08:00
fit2bot
2414f34a5a perf: 优化 apt (#8398)
* pref: 修改 oracle lib path

* perf: 优化 apt

Co-authored-by: ibuler <ibuler@qq.com>
2022-06-14 19:59:00 +08:00
Jiangjie.Bai
2aebfa51b2 fix: 过滤系统用户密码过滤ansible不支持的字符 2022-06-14 18:49:35 +08:00
feng626
f91bfedc50 perf: 授权过期通知 2022-06-14 18:33:49 +08:00
Jiangjie.Bai
68aad56bad Merge pull request #8379 from jumpserver/dev
v2.23.0-rc3
2022-06-13 17:42:31 +08:00
ibuler
556ce0a146 perf: 继续优化一波 2022-06-13 16:46:14 +08:00
Jiangjie.Bai
95f8b12912 fix: 修复部分 password encrypted field extra kwargs 参数不生效问题 2022-06-13 16:44:01 +08:00
fit2bot
25ae790f7d fix: 修改client 版本 (#8375)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-13 15:45:10 +08:00
ibuler
0464b1a9e6 perf: 优化迁移 rbac 速度
perf: migrate
2022-06-13 15:18:15 +08:00
Jiangjie.Bai
3755f8f33a fix: 修复推送动态用户 comment 中包含空格导致推送失败的问题 2022-06-13 14:54:29 +08:00
Jiangjie.Bai
85b2ec2e6a Merge pull request #8362 from jumpserver/dev
v2.23.0-rc2
2022-06-10 19:12:17 +08:00
Jiangjie.Bai
9d1e94d3c2 fix: 修复手动登录系统用户连接RemoteApp应用获取不到认证信息的问题 2022-06-10 18:35:39 +08:00
Jiangjie.Bai
be75edcb41 Merge pull request #8353 from jumpserver/dev
v2.23.0-rc1
2022-06-09 17:40:10 +08:00
ibuler
a5c6ba6cd6 perf: 优化 perm app node 2022-06-09 10:48:48 +08:00
fit2bot
81ef614820 fix: relogin重置MFA_VERIFY_TIME (#8348)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-08 19:32:50 +08:00
ibuler
c6949b4f68 perf: 去掉 remote app 的加密 2022-06-08 10:04:14 +08:00
fit2bot
a5acdb9f60 perf: 统一校验当前用户api (#8324)
Co-authored-by: feng626 <1304903146@qq.com>
2022-06-07 19:26:07 +08:00
Jiangjie.Bai
2366f02d10 feat: 添加组件类型 razor 并替换 XRDP_ENABLED 2022-06-07 13:43:53 +08:00
Jiangjie.Bai
dade0cadda feat: 克隆角色权限 2022-06-06 16:13:12 +08:00
ibuler
e096244e75 pref: app tree 添加 icon 2022-06-06 14:00:34 +08:00
Jiangjie.Bai
3bc307d666 perf: 设置Connection Token 默认最少5分钟 (#8331) 2022-06-01 18:00:22 +08:00
Jiangjie.Bai
810c500402 feat: 添加配置项 CONNECTION_TOKEN_EXPIRATION 2022-05-31 18:23:48 +08:00
fit2bot
6c0d0c3e92 feat: OIDC 用户添加属性映射值 (#8327)
* feat: OIDC 用户添加属性映射值

* feat: OIDC 用户添加属性映射值

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-05-31 16:09:31 +08:00
Jiangjie.Bai
af1150bb86 feat: OIDC 用户添加属性映射值 2022-05-31 16:03:39 +08:00
ibuler
f7cbcc46f4 perf: 升级 ansible version 2022-05-31 16:01:21 +08:00
ibuler
327c6beab4 fix: 修复假数据构造 2022-05-30 16:39:47 +08:00
ibuler
196663f205 perf: 修改生成假数据 2022-05-30 16:03:13 +08:00
Jiangjie.Bai
15423291cc fix: 修复ldap用户登录时用户组不设置 2022-05-30 16:02:50 +08:00
ibuler
021635b850 perf: 优化 readme 2022-05-30 15:09:04 +08:00
老广
992c1407b6 Update README.md (#8316)
* Update README.md

* Update README.md

* Update README.md

* Update README.md
2022-05-30 14:51:29 +08:00
Chayim I. Kirshen
1322106c91 bumping redis-py to 4.3.1 (latest) 2022-05-30 13:30:25 +08:00
Jiangjie.Bai
42202bd528 fix: 修改 public settings API公告字段类型为 dict 2022-05-27 17:24:09 +08:00
fit2bot
b24d2f628a perf: update download (#8304)
Co-authored-by: feng626 <1304903146@qq.com>
2022-05-27 14:14:47 +08:00
fit2bot
041302d5d2 fix: 修复获取 city 时可能的报错 (#8294)
Co-authored-by: ibuler <ibuler@qq.com>
2022-05-24 12:31:16 +08:00
feng626
a08dd5ee72 fix: 修复用户更新自己密码 url 不准确问题 2022-05-24 11:16:13 +08:00
ibuler
09ef72a4a8 fix: 修复 Migrations 错误 2022-05-24 11:01:26 +08:00
ibuler
26cf64ad2d perf: 修改 i18 2022-05-20 11:41:33 +08:00
ibuler
0a04f0f351 perf: 下载 ip 数据库 2022-05-20 10:03:13 +08:00
fit2bot
1029556902 perf: remote app 字段也加密 (#8274)
* perf: remote app 字段也加密

* perf: 修改一些加密字段

Co-authored-by: ibuler <ibuler@qq.com>
2022-05-20 10:01:41 +08:00
Jiangjie.Bai
c41fc54380 Merge pull request #8271 from jumpserver/dev
v2.22.0-rc4
2022-05-18 20:21:35 +08:00
feng626
c2fbe5c75a fix: 不支持es8 提示 2022-05-18 20:20:54 +08:00
feng626
99e1b2cf92 fix: 不支持es8 提示 2022-05-18 20:14:31 +08:00
Jiangjie.Bai
33090c4cdf Merge pull request #8268 from jumpserver/dev
v2.22.0-rc4
2022-05-18 19:49:11 +08:00
fit2bot
c8d7c7c56f fix: 修复oidc认证不区分大小写 (#8267)
Co-authored-by: feng626 <1304903146@qq.com>
2022-05-18 18:32:53 +08:00
ibuler
aa7540045b feat: 添加 session guard 2022-05-18 14:55:58 +08:00
ibuler
e5f4b8000e stash 2022-05-18 14:55:58 +08:00
ibuler
44ffd09924 fix: 修复可能的 decode error 2022-05-18 10:17:15 +08:00
ibuler
fe3059c1fd fix: 修复获取密码失败 2022-05-17 23:50:30 +08:00
Jiangjie.Bai
b76920a4bf fix: 修改组织资源统计时 org 为None的问题 2022-05-17 22:11:42 +08:00
ibuler
b5ac5c5670 perf: domain gateway 也添加 2022-05-17 21:36:40 +08:00
ibuler
c3c0f87c01 perf: domain gateway 也添加 2022-05-17 21:32:31 +08:00
Jiangjie.Bai
d672122c79 Merge pull request #8260 from jumpserver/dev
v2.22.0-rc3
2022-05-17 21:14:05 +08:00
fit2bot
0c71190337 fix: 修改 EncryptedField 字段的 write_only 属性 (#8259)
* fix: 修改 EncryptedField 字段的 write_only 属性

fix: 修改 EncryptedField 字段的 write_only 属性

* fix: 修改 EncryptedField 字段的 write_only 属性

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-05-17 21:12:59 +08:00
feng626
14710e9c9e feat: 工单审批人中去除申请人 2022-05-17 20:56:53 +08:00
ibuler
7eec50804c perf: 优化 encrypted field 2022-05-17 20:04:46 +08:00
Jiangjie.Bai
0fc5a33983 fix: 修复企业微信、钉钉、飞书登录跳转问题 2022-05-17 18:57:49 +08:00
fit2bot
07779c5a7a perf: 工单启用 (#8254)
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-05-17 18:57:04 +08:00
fit2bot
d675b1d4fc fix: k8s token 解密 (#8252)
Co-authored-by: feng626 <1304903146@qq.com>
2022-05-17 16:53:15 +08:00
Jiangjie.Bai
514fa9cf0a Merge pull request #8250 from jumpserver/dev
v2.22.0-rc2
2022-05-17 15:10:59 +08:00
ibuler
2c73611cb4 fix: 修复公告不显示的问题 2022-05-17 11:30:37 +08:00
ibuler
83571718e9 perf: 修改版本 2022-05-16 20:02:10 +08:00
ibuler
521ec0245b fix: ipdb 版本 2022-05-16 20:02:10 +08:00
jiangweidong
e80b6936a2 perf: 兼容AWS上redis[ssl]无证书无法部署的问题 2022-05-16 18:03:47 +08:00
Jiangjie.Bai
2c4f937e0b fix: 解决LDAP同步用户仪表盘总数没有刷新的问题 2022-05-16 17:52:49 +08:00
Jiangjie.Bai
2a5497de14 fix: 修改工单审批文案 2022-05-16 17:52:27 +08:00
feng626
d87dc7cbd6 fix: import ipdb 2022-05-16 17:51:37 +08:00
fit2bot
3b253e276c perf: 优化翻译 (#8244)
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-05-16 17:50:28 +08:00
feng626
525538e775 fix: 修复密码密钥翻译问题 2022-05-16 17:48:28 +08:00
ibuler
2a8f8dd709 perf: 优化使用两个 ip 库 2022-05-16 15:24:38 +08:00
ibuler
1e6e59d815 perf: 添加 ipdb 2022-05-16 15:24:38 +08:00
ibuler
475678e29b fix: 修复密码 write only 2022-05-16 12:19:52 +08:00
Jiangjie.Bai
7f52675bd3 Merge pull request #8229 from jumpserver/dev
v2.22.0 rc1
2022-05-12 17:02:01 +08:00
fit2bot
6409b7deee feat: Endpoint添加Redis Port (#8225)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-05-12 14:47:35 +08:00
ibuler
4f37b2b920 perf: 优化 setting 读取,避免遗漏 2022-05-12 11:52:44 +08:00
fit2bot
c692eed3c6 perf: 修改client 版本 (#8223)
Co-authored-by: feng626 <1304903146@qq.com>
2022-05-12 10:59:19 +08:00
ibuler
dab8828b03 perf: 优化 setting 获取 2022-05-11 17:57:33 +08:00
ibuler
d692188a34 perf: 修改 i18n 2022-05-11 16:03:26 +08:00
Jiangjie.Bai
bc8df72603 fix: 修改创建更新用户的密码字段 2022-05-11 16:02:56 +08:00
Jiangjie.Bai
bf466a1ba2 feat: LDAP同步用户支持组织 2022-05-11 11:09:30 +08:00
fit2bot
aff5b0035d perf: 优化加密 (#8206)
* perf: 优化加密

* perf: 优化加密

* perf: 优化加密传输

Co-authored-by: ibuler <ibuler@qq.com>
2022-05-10 17:28:10 +08:00
jiangweidong
b44fa64994 perf: 企业微信、钉钉工单审批增加拒绝功能 (#8208)
* perf: 工单直接审批增加拒绝功能

* feat: 翻译

* perf: 修改动作名词

* perf: 修改翻译
2022-05-10 16:30:25 +08:00
ibuler
094446c548 chore: 去掉一个workflow 2022-05-10 10:37:01 +08:00
jiangweidong
64eda5f28b perf: 命令存储ES可根据日期动态建立索引 (#8180)
* perf: 命令存储ES可根据日期动态建立索引

* perf: 优化合并字段

* feat: 修改逻辑
2022-05-09 16:37:31 +08:00
Jiangjie.Bai
ab737ae09b fix: 修复获取类型为null的命令显示不支持的问题
fix: 修复获取类型为null的命令显示不支持的问题
2022-05-07 17:56:50 +08:00
jiangweidong
55e04e8e9f feat: 内置AIX系统,根据系统选择算法加密密码 2022-05-07 16:25:03 +08:00
jiangweidong
5e70a8af15 feat: 支持平台关联算法,支持AIX改密 2022-05-07 16:25:03 +08:00
fit2bot
031077c298 perf: password 等使用 rsa 加密传输 (#8188)
* perf: 修改 model fields 路径

* stash it

* pref: 统一加密方式,密码字段采用 rsa 加密

* pref: 临时密码使用 rsa

* perf: 去掉 debug msg

* perf: 去掉 Debug

* perf: 去掉 debug

* perf: 抽出来

Co-authored-by: ibuler <ibuler@qq.com>
2022-05-07 16:20:12 +08:00
Jiangjie.Bai
3f856e68f0 feat: public settings 区分 public 和 open 2022-05-07 11:09:24 +08:00
fit2bot
56862a965d fix: 修复system-role获取users失败的问题 (#8196)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-05-07 10:40:12 +08:00
jiangweidong
e151548701 perf: 账号管理中查看密码记录日志 (#8157) 2022-05-05 14:42:09 +08:00
jiangweidong
c56179e9e4 feat: 支持企业微信、钉钉直接审批工单 (#8115) 2022-05-05 13:07:48 +08:00
feng626
d23953932f perf: connection token 分api权限 2022-05-05 11:45:26 +08:00
Jiangjie.Bai
2493647e5c fix: 修复windows执行ansible显示sudo失败的问题 2022-05-05 11:40:12 +08:00
Jiangjie.Bai
00ed7bb025 perf: 优化 OIDC 支持选择认证方式 2022-04-29 14:28:07 +08:00
xiaziheng
b1aadf1ee9 Fix oidc (#8165) 2022-04-29 10:59:29 +08:00
feng626
86e6982383 fix: 组织管理员 添加 view platform perm 2022-04-28 19:10:58 +08:00
halo
dc42d1caa2 perf: 修改ssh_client连接选项翻译 2022-04-28 19:09:44 +08:00
ibuler
cb5d8fa13f fix: 去掉自动生成的map文件 2022-04-26 16:46:47 +08:00
jiangweidong
3a3f7eaf71 feat: 优化SAML2生成的metadata文件内容及属性映射 2022-04-26 10:00:53 +08:00
fit2bot
9804ca5dd0 fix: workbench_orgs 去重 (#8150)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-25 11:38:15 +08:00
老广
034d0e285c Update README.md 2022-04-24 17:47:02 +08:00
feng626
104d672634 perf: client download 2022-04-24 15:09:33 +08:00
ibuler
529e3d12e0 perf: 删除 build 2022-04-24 09:12:29 +08:00
ibuler
978c1f6363 perf: 修改 Dockerfile, 优化构建 2022-04-24 09:12:29 +08:00
ibuler
d25cde1bd5 fix: 修复社区版跳转问题 2022-04-21 22:48:59 +08:00
Jiangjie.Bai
a4be0ff2f3 Merge pull request #8131 from jumpserver/dev
v2.21.0
2022-04-21 18:11:21 +08:00
Jiangjie.Bai
a6d61721dd fix: 修改csrftoken获取问题 2022-04-21 16:17:33 +08:00
fit2bot
c3de7b78c2 fix: 远程应用授权时 有些资产已经不存在了 导致授权失败 (#8127)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-21 15:36:40 +08:00
Jiangjie.Bai
e83d676712 Merge pull request #8119 from jumpserver/dev
v2.21.0-rc6
2022-04-20 20:25:43 +08:00
Jiangjie.Bai
63ee2dd8fb fix: 修复获取权限树权限控制 2022-04-20 20:14:44 +08:00
feng626
74f88d842d fix: 修改replay download perm 2022-04-20 19:14:42 +08:00
fit2bot
e61bae5ee4 perf: 优化权限位 (#8110)
* perf: 优化权限位

* perf: 优化返回的组织

* perf: 保证结果是 ok

* perf: 去掉 distinct

* perf: tree count

Co-authored-by: ibuler <ibuler@qq.com>
2022-04-20 18:50:53 +08:00
fit2bot
b0b379e5a9 fix: del org check ldap (#8114)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-20 16:38:42 +08:00
fit2bot
415521a003 fix: 删除组织时检测ldap同步组织 (#8112)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-20 16:32:33 +08:00
Jiangjie.Bai
c29d133776 feat: 修改LDAP导入定时任务interval/crontab优先级
Signed-off-by: Jiangjie.Bai <bugatti_it@163.com>
2022-04-20 16:31:56 +08:00
fit2bot
d2dd487e2c feat: 修改LDAP导入组织问题 (#8111)
Signed-off-by: Jiangjie.Bai <bugatti_it@163.com>

Co-authored-by: BaiJiangJie <bugatti_it@163.com>
2022-04-20 16:05:33 +08:00
ibuler
f1bd4ea91f perf: 修改 系统级别用户角色的 perms 2022-04-20 11:50:11 +08:00
fit2bot
7647438792 perf: 账号备份log (#8106)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-20 11:18:50 +08:00
Jiangjie.Bai
015ff4b119 Merge pull request #8105 from jumpserver/dev
v2.21.0-rc5
2022-04-20 10:46:27 +08:00
fit2bot
af9248ef7c fix: 还原connection token 逻辑 (#8101)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-20 10:24:08 +08:00
Jiangjie.Bai
c04ab1aab9 Merge pull request #8100 from jumpserver/dev
v2.21.0-rc5
2022-04-19 21:52:51 +08:00
feng626
611a00a5fa fix: 修复super user perm bug 2022-04-19 21:52:01 +08:00
Jiangjie.Bai
57969a4e23 fix: 修改获取smart endpoint的逻辑 2022-04-19 19:50:18 +08:00
Jiangjie.Bai
5f370c1c04 perf: 优化内置系统用户角色权限 2022-04-19 19:19:47 +08:00
Jiangjie.Bai
f026b86a20 fix: 修复获取组织用户 2022-04-19 18:09:07 +08:00
ibuler
0addba7c14 perf: 修改 command 命令执行 2022-04-19 17:21:27 +08:00
ibuler
e4b0ab6a45 perf: 修改命令执行区分组织 2022-04-19 17:21:27 +08:00
Jiangjie.Bai
b4ac24ad6d fix: 修改endpoint/rule权限树位置 2022-04-19 17:21:09 +08:00
halo
500477fad1 fix: ftp日志清理bug 2022-04-19 17:13:17 +08:00
Jiangjie.Bai
3b9cb2a99c fix: 修改翻译临时密码 2022-04-19 16:26:33 +08:00
Jiangjie.Bai
f8fade4cf2 feat: 添加配置项 KoKo SSH Client 方式 2022-04-19 16:16:55 +08:00
Jiangjie.Bai
be2708f83d fix: 修复ajax请求携带csrftoken问题 2022-04-19 14:29:23 +08:00
ibuler
516cb05d69 perf: 修改翻译 2022-04-19 13:33:28 +08:00
老广
714b6b1233 Merge pull request #8085 from jumpserver/dev
v2.21.0-rc5
2022-04-19 13:15:16 +08:00
ibuler
3e3835dc28 perf: 修改用户权限 2022-04-19 10:42:36 +08:00
ibuler
f4ed4e1176 perf: 添加 temp token 排序 2022-04-18 19:55:16 +08:00
feng626
7b2d51f343 fix: 修复角色过滤失败 2022-04-18 19:54:44 +08:00
feng626
fe47e40588 fix: es6 create index fail 2022-04-18 19:44:54 +08:00
fit2bot
4362f8d5af perf: 优化组织 (#8080)
* perf: 优化用户的orgs

* perf: 优化组织

Co-authored-by: ibuler <ibuler@qq.com>
2022-04-18 17:17:23 +08:00
Jiangjie.Bai
6f49d240af Merge pull request #8079 from jumpserver/dev
v2.21.0-rc4
2022-04-18 15:31:02 +08:00
Jiangjie.Bai
3eab621b28 feat: 优化Endpoint迁移逻辑,增加XRDP规则和Endpoint
fix: 修改Endpoint迁移文件
2022-04-18 15:29:40 +08:00
Jiangjie.Bai
afcbe60531 Merge pull request #8076 from jumpserver/dev
v2.21.0-rc3
2022-04-18 11:43:40 +08:00
jiangweidong
548a374c6d fix: 修复部署在没有密码的redis上时,站内信数量不更新问题 2022-04-18 11:39:20 +08:00
feng626
10c146b07d fix: 修复远程应用无资产下载xrdp file 500 问题 2022-04-18 11:38:31 +08:00
fit2bot
a647e73c02 feat: 设置SessionCookieNamePrefix (#8071)
* feat: 设置SessionCookieNamePrefix

* feat: 设置SessionCookieNamePrefix

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-04-15 21:33:15 +08:00
Jiangjie.Bai
7b02777f1e fix: 修改endpoint smart API允许有效用户访问 2022-04-15 16:33:41 +08:00
Jiangjie.Bai
97e59384e0 fix: connection token API 返回有效时间 2022-04-15 16:33:20 +08:00
jiangweidong
70a07539af perf: 优化部分云厂商的redis连接的问题 2022-04-15 10:00:49 +08:00
Jiangjie.Bai
f98c170b8c Merge pull request #8061 from jumpserver/dev
v2.21.0-rc2
2022-04-14 19:51:29 +08:00
fit2bot
0b94d7414a feat: download (#8062)
Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2022-04-14 19:51:10 +08:00
feng626
7aa0c9bf19 feat: download 2022-04-14 15:00:59 +08:00
Jiangjie.Bai
6d8e8856ac fix: 修改命令timestamp_display只读 2022-04-14 14:45:19 +08:00
Jiangjie.Bai
c240a471dc fix: Public Setting 添加 Magnus 2022-04-14 14:16:02 +08:00
Jiangjie.Bai
ea478fc801 fix: Public Setting 添加 Magnus 2022-04-14 12:55:18 +08:00
fit2bot
5127214375 feat: 站内信一键已读 (#8057)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-14 12:18:11 +08:00
Jiangjie.Bai
21c41a6334 Merge pull request #8054 from jumpserver/dev
v2.21.0-rc1
2022-04-13 20:25:47 +08:00
fit2bot
b610d71e11 feat: 添加 临时 password (#8035)
* perf: 添加 template password

* perf: 修改id

* perf: 修改 翻译

* perf: 修改 tmp token

* perf: 修改 token

Co-authored-by: ibuler <ibuler@qq.com>
2022-04-13 20:24:56 +08:00
Jiangjie.Bai
10b033010e feat: 优化命令导出时间戳可读性 2022-04-13 19:50:17 +08:00
fit2bot
c630b11bd5 fix: port str (#8055)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-13 19:48:31 +08:00
ibuler
b0f7c114fc perf: 修改 csrf token domain 2022-04-13 16:08:07 +08:00
fit2bot
72608146cc chore: lgtm (#8048)
* chore: lgtm

* perf: add lgtm

Co-authored-by: ibuler <ibuler@qq.com>
2022-04-12 18:25:28 +08:00
ibuler
3213fe0984 chore: 添加action lgtm 2022-04-12 18:06:42 +08:00
fit2bot
f481463c64 feat: 添加Endpoint (#8041)
* feat: add Endpoint EndpointRule EndpointProtocol model

* feat: add Endpoint EndpointRule EndpointProtocol API

* feat: modify protocols field

* feat: 修改序列类

* feat: 获取connect-url连接地址

* feat: 获取connect-url连接地址

* feat: 优化后台获取smart-endpoint逻辑

* feat: 优化后台获取smart-endpoint逻辑

* feat: 删除配置KOKO、XRDP、MAGNUS

* feat: 删除配置KOKO、XRDP、MAGNUS

* feat: 修改翻译

* feat: 修改smart endpoint

* feat: 修改翻译

* feat: smart API 添加token解析

* feat: 删除 smart serializer

* feat: 修改迁移逻辑

* feat: 解决冲突

* feat: 修改匹配 endpoint

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-04-12 17:45:10 +08:00
ibuler
4cf90df17c perf: 默认角色添加 created by 2022-04-12 16:20:46 +08:00
ibuler
ffd98c6e3f fix: 修改 import 2022-04-12 16:20:46 +08:00
fit2bot
1f8ded49fa feat: 工作台区分组织 (#8040)
* perf: 工作台受组织角色控制

* perf: workspace => workbench

* perf: 修改 workspace codename

Co-authored-by: ibuler <ibuler@qq.com>
2022-04-12 14:25:49 +08:00
fit2bot
7c7d7d52b2 perf: asset number 扩容 (#8045)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-12 14:01:57 +08:00
feng626
f769d5a9bb fix: 修复用户数据不同步问题 2022-04-08 15:47:14 +08:00
feng626
c8758f417d feat: ldap一键导入及设置用户组织 2022-04-06 17:13:34 +08:00
Eric
ef36b2e662 perf: 完善 setting 的动态配置 2022-04-06 16:45:22 +08:00
jiangweidong
fe8527fd07 feat: 修改翻译 2022-04-02 16:04:13 +08:00
feng626
2cb08b4785 fix: user is common user 2022-04-02 16:02:57 +08:00
fit2bot
a936092020 perf: es相关代码格式优化 (#8020)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-02 13:26:18 +08:00
fit2bot
e602bc0341 fix: 修复网关翻译 (#8016)
Co-authored-by: feng626 <1304903146@qq.com>
2022-04-01 16:52:50 +08:00
Jiangjie.Bai
3121b4e3ff feat: 更新翻译 2022-03-31 13:05:55 +08:00
Jiangjie.Bai
eff562505e feat: 更新翻译 2022-03-31 13:05:55 +08:00
Jiangjie.Bai
73cb5e10b4 fix: 添加用户不能自更新字段逻辑 & 修复用户is_active创建失败的问题
fix: 添加用户不能自更新字段逻辑 & 修复用户is_active创建失败的问题

fix: 添加用户不能自更新字段逻辑 & 修复用户is_active创建失败的问题
2022-03-30 19:52:45 +08:00
fit2bot
c58d245636 fix: 修复koko setting (#8005)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-30 19:51:56 +08:00
fit2bot
e7af037513 perf: 修改命令command input 长度问题 (#7996)
* perf: 修改命令command input max_length 1024

* perf: 修改命令command input 长度问题

* perf: 修改命令command input 长度问题

* perf: 修改命令command input 长度问题

* perf: 修改命令command input 长度问题

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-30 19:07:49 +08:00
Jiangjie.Bai
54d1996507 feat: 支持续期Connection Token 2022-03-30 11:20:56 +08:00
dependabot[bot]
71f8b40e21 build(deps): bump paramiko from 2.7.2 to 2.10.1 in /requirements
Bumps [paramiko](https://github.com/paramiko/paramiko) from 2.7.2 to 2.10.1.
- [Release notes](https://github.com/paramiko/paramiko/releases)
- [Changelog](https://github.com/paramiko/paramiko/blob/main/NEWS)
- [Commits](https://github.com/paramiko/paramiko/compare/2.7.2...2.10.1)

---
updated-dependencies:
- dependency-name: paramiko
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-30 11:06:49 +08:00
ibuler
59342a88c0 perf: 优化各种翻译 2022-03-29 19:33:38 +08:00
fit2bot
b8e6bc932b perf: 添加 mariadb port (#7989)
* perf: 添加 mariadb port

* perf: 优化 mariadb 树上天津更多信息

* perf: remove mixin

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-29 17:22:59 +08:00
Jiangjie.Bai
cddff9fd19 feat: 改密计划支持su切换用户执行
feat: 改密计划支持su切换用户执行

feat: 改密计划支持su切换用户执行

feat: 改密计划支持su切换用户执行

feat: 改密计划支持su切换用户执行

feat: 改密计划支持su切换用户执行

feat: 改密计划支持su切换用户执行
2022-03-29 15:32:33 +08:00
feng626
d856f1364a feat: 拉起ssh api 2022-03-29 13:23:58 +08:00
fit2bot
52709d2efa feat: 企业微信、钉钉 工作台免密登录(飞书已实现) (#7855)
* feat: 添加oauth接口

* feat: 企业微信支持OAuth认证,工作台免密登录

* feat: 钉钉支持OAuth认证,工作台免密登录

* fix: 修复参数错误

Co-authored-by: halo <wuyihuangw@gmail.com>
2022-03-29 13:19:13 +08:00
ibuler
a20de3df16 perf: app tree 添加attrs,luna 使用 2022-03-29 12:44:36 +08:00
ibuler
e303b4f571 perf: 修复 settings patch 问题 2022-03-28 13:40:36 +08:00
jiangweidong
03fdaa03e4 feat: 支持日语 2022-03-28 10:06:54 +08:00
fit2bot
b7b1d81ea0 fix: magenus bug (#7977)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-25 16:46:36 +08:00
fit2bot
e0fdfa52b9 feat: 支持 magnus (#7965)
* feat: 支持 magnus

* perf: 添加 setting 到 api

* perf: 放出 mongodb

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-25 14:45:08 +08:00
ibuler
8718dc6751 pref: 优雅一发 2022-03-25 14:44:33 +08:00
ibuler
9e284f96e5 perf: 修改依赖写法,避免 github 认错 2022-03-25 14:44:33 +08:00
Eric
fc06295d04 perf: 优化 windows rdp 窗口显示 2022-03-25 10:50:34 +08:00
fit2bot
9b73727bbc fix: 修复系统组件绑定角色bug (#7962)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-23 10:56:23 +08:00
Jiangjie.Bai
6bde31cdd0 fix: 修复获取远程应用认证信息问题 2022-03-22 18:54:25 +08:00
ibuler
2721793b8f fix: 修复权限 view 没有 Model 的问题 2022-03-22 16:59:01 +08:00
feng626
2ec0cb8a2c fix: 修复用户绑定角色重大bug 2022-03-22 16:55:53 +08:00
feng626
d01d44b48d fix: api docs 2022-03-22 13:05:44 +08:00
老广
0ef7a9571c Merge pull request #7800 from jumpserver/pr@dev@feat_core_redis_support_ssl
feat: JumpServer支持部署在使用了ssl的redis上
2022-03-22 10:34:32 +08:00
ibuler
54fd1fb0c8 perf: 移动到信号中 2022-03-21 19:27:23 +08:00
ibuler
87c6eec619 perf: 优化 role bingding,优化 is_superuser 2022-03-21 19:27:23 +08:00
jiangweidong
e35fbfc7e9 Update session.py 2022-03-21 19:02:30 +08:00
fit2bot
3345456dc2 fix: 修复wateway api (#7947)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-21 17:53:16 +08:00
Jiangjie.Bai
9ae74120ed fix: 修复用户API权限 2022-03-21 12:00:15 +08:00
Jiangjie.Bai
9e5c132485 fix: 修复用户API权限 2022-03-21 11:58:29 +08:00
fit2bot
5cc2fdae4f fix: 修复api docs打不开的问题 (#7938)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-21 11:14:49 +08:00
jiangweidong
e993f31b6d feat: 支持纳管百度云资产 (#7921)
Co-authored-by: ibuler <ibuler@qq.com>
2022-03-21 10:39:47 +08:00
Jiangjie.Bai
60edbb36a1 fix: 应用树隐藏mongodb节点 2022-03-18 18:02:15 +08:00
fit2bot
5da1ec55a7 perf: org del ticket perm (#7932)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-18 17:44:20 +08:00
Jiangjie.Bai
b8c083af7e fix: 工单权限位放到sys角色中 2022-03-18 17:36:22 +08:00
Jiangjie.Bai
996621f303 fix: 移除权限dashboard 2022-03-18 17:10:34 +08:00
fit2bot
ec9e5da653 fix: 修复apikey perm (#7918)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-18 15:53:34 +08:00
Jiangjie.Bai
d4e4015d91 fix: 修复去除rolebiding change 权限 2022-03-18 15:38:33 +08:00
Jiangjie.Bai
005dd27701 Merge pull request #7917 from jumpserver/dev
v2.20.0
2022-03-17 19:22:22 +08:00
Jiangjie.Bai
ac6052546a fix: 修改翻译 2022-03-17 19:20:39 +08:00
Jiangjie.Bai
0265adcc72 fix: 修改翻译 2022-03-17 19:20:39 +08:00
Jiangjie.Bai
9654083662 fix: 修改站内信权限位 2022-03-17 19:06:44 +08:00
fit2bot
08ff8fa285 fix: login confirm bug (#7914)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-17 18:50:37 +08:00
Jiangjie.Bai
f82f7eba2b fix: 修改一些权限 2022-03-17 17:51:02 +08:00
Jiangjie.Bai
a8cee26874 fix: 修复资产详情授权用户tab页的权限位 2022-03-17 17:25:20 +08:00
Jiangjie.Bai
8080d36d90 Merge pull request #7911 from jumpserver/dev
v2.20.0-rc6
2022-03-17 17:07:22 +08:00
ibuler
3ed7477057 perf: 修改 default role 2022-03-17 16:53:29 +08:00
ibuler
a3cddd5d34 fix: 修复批量命令的bug 2022-03-17 16:26:22 +08:00
Jiangjie.Bai
26b3c60e5c fix: 删除一些perms相关的权限位 2022-03-17 16:26:00 +08:00
ibuler
b5dea38164 perf: 修改bug 2022-03-17 16:09:51 +08:00
ibuler
7addb881f6 fix: 修复系统用户Perms 2022-03-17 16:09:51 +08:00
fit2bot
9c395b674f fix: command log search (#7906)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-17 15:39:05 +08:00
Jiangjie.Bai
b297ebe973 fix: 修改应用category 2022-03-17 15:37:57 +08:00
fit2bot
5c7bfcff1c perf: 修改 i18n (#7904)
* perf: some perm to xpack

* perf: 修改 i18n

* perf: 修改 i18n

* perf: 修改 i18n

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-03-17 15:23:22 +08:00
fit2bot
76796f249d fix: user match (#7903)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-17 14:47:24 +08:00
Jiangjie.Bai
55a63477ed fix: 去除系统用户资产相关权限 2022-03-17 14:38:19 +08:00
ibuler
5942037d81 perf: some perm to xpack 2022-03-17 14:24:52 +08:00
Jiangjie.Bai
5882b8a682 fix: 去除application secret change perm 2022-03-17 14:24:25 +08:00
fit2bot
34e75099a3 perf: 设置默认的角色,系统用户角色添加权限 (#7898)
* perf: 修改 role handler

* perf: 设置默认的角色,系统用户角色添加权限

* perf: authentication 还是放到系统中吧

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-03-17 14:08:16 +08:00
feng626
8fe84345e4 fix: 工单默认权限 2022-03-17 14:06:34 +08:00
Jiangjie.Bai
a31c3ccc30 fix: 去除application account delete perm 2022-03-17 14:05:08 +08:00
Jiangjie.Bai
e13e34098a fix: 站内信命令告警中的会话地址 2022-03-17 14:05:08 +08:00
feng626
e8653c74cd fix: ticket URL type 2022-03-17 12:35:08 +08:00
feng626
1433c35ff9 fix: test gateway 2022-03-17 12:33:59 +08:00
Jiangjie.Bai
a237b5a63d fix: 去掉terminal task add/delete 权限位 2022-03-17 11:40:54 +08:00
feng626
2587c8693e fix: account_change_pwd 2022-03-17 11:36:48 +08:00
feng626
dfe5e2bce3 fix: 修改rbac permission 2022-03-17 11:36:48 +08:00
Jiangjie.Bai
91a34d1a88 Merge pull request #7888 from jumpserver/dev
v2.20.0-rc5
2022-03-16 20:49:53 +08:00
Jiangjie.Bai
1a05a942c2 fix: 更新资产详情授权用户权限 2022-03-16 20:49:29 +08:00
Jiangjie.Bai
30556023d1 fix: 修复会话录像播放权限 2022-03-16 20:42:38 +08:00
fit2bot
aa022a02c1 fix: 修复用户认证失败的详细信息显示 (#7886)
* fix: 修复用户认证失败的详细信息显示

* fix: 更新授权树翻译

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-03-16 20:41:54 +08:00
fit2bot
433d829c29 fix: 添加profile myorgs (#7887)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-16 20:36:12 +08:00
fit2bot
3b507dc795 perf: 优化英文下树的显示 (#7883)
* perf: 优化英文下树的显示

* perf: 修改翻译

* perf: 修改翻译

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-16 20:27:38 +08:00
Jiangjie.Bai
8233c69038 fix: 修复adhoc权限 2022-03-16 19:26:40 +08:00
ibuler
0fbc548c02 fix: 修复访问 flower 错误 2022-03-16 19:05:06 +08:00
Jiangjie.Bai
aa9ae14e46 fix: 修复view action获取 2022-03-16 18:33:55 +08:00
Jiangjie.Bai
04b35ba520 fix: 修复批量命令权限位 2022-03-16 18:33:13 +08:00
ibuler
580d2cd80b perf: 修改 org admin 2022-03-16 18:26:16 +08:00
ibuler
da9136f7af perf: 修改 org role 2022-03-16 18:26:16 +08:00
ibuler
1ce2706f20 perf: 修改翻译 2022-03-16 18:26:16 +08:00
ibuler
bbdeba3659 perf: 修复 org admin all 2022-03-16 18:26:16 +08:00
feng626
3a26b9d102 fix: 修复工单相应bug 2022-03-16 17:40:51 +08:00
ibuler
ee757e261d perf: 修改写法 2022-03-16 17:14:42 +08:00
ibuler
f41e6db007 perf: sso token 只能超级管理员 2022-03-16 17:14:42 +08:00
ibuler
7eed7b32cc perf: 修复 org role binding 在root组织下看到的可能不对 2022-03-16 17:14:42 +08:00
Jiangjie.Bai
efb26132f6 fix: 修复sso用户登录失败的问题 2022-03-16 17:11:22 +08:00
Jiangjie.Bai
572c5b6925 fix: 修改工单管理权限位 2022-03-16 14:54:50 +08:00
ibuler
8a1cd7e2a9 perf: fix some bug 2022-03-16 14:18:01 +08:00
Jiangjie.Bai
c065f82d30 fix: 排除收集用户执行的更新、删除权限位 2022-03-16 14:17:35 +08:00
ibuler
995c9a6c19 perf: 修复一些bug, rolebingding 找到合适的 2022-03-16 14:08:54 +08:00
Jiangjie.Bai
5ec970fab4 fix: 全局组织受权限位控制 2022-03-16 14:07:00 +08:00
Jiangjie.Bai
166745baf6 Merge pull request #7866 from jumpserver/dev
v2.20.0 rc4
2022-03-15 20:54:40 +08:00
Jiangjie.Bai
d320443c9f fix: 去除change_setting权限位 2022-03-15 20:25:18 +08:00
ibuler
4bfa88f01f perf: 修改 app tree 2022-03-15 20:09:30 +08:00
Jiangjie.Bai
aedd8ba589 fix: 修复查看我的应用翻译 2022-03-15 19:51:59 +08:00
Jiangjie.Bai
172b492bc3 fix: 修复存储测试权限位 2022-03-15 19:41:25 +08:00
Jiangjie.Bai
c4280d259a fix: 修复翻译/权限设置 2022-03-15 19:18:01 +08:00
Jiangjie.Bai
b25ec559bb fix: 修复翻译/权限设置 2022-03-15 19:18:01 +08:00
ibuler
cd46c8c78e perf: 发送验证码,不再提示 2022-03-15 18:47:12 +08:00
ibuler
8839e6293b perf: 修改 mfa 地址 2022-03-15 18:47:12 +08:00
ibuler
4f887b1b11 perf: 优化 tree node icon 2022-03-15 18:46:11 +08:00
fit2bot
90840a4417 fix: 工单创建bug (#7858)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-15 18:22:13 +08:00
fit2bot
a18b9bad0a fix:  修复ticketsession (#7857)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-15 17:32:54 +08:00
feng626
e1a238b778 fix: 删除资产授权缓存接口 2022-03-15 16:55:45 +08:00
吴小白
ee44ae2e12 perf: 优化构建速度 2022-03-15 16:55:10 +08:00
fit2bot
d77e84e6f8 fix: ticket comment bug (#7854)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-15 16:50:51 +08:00
Jiangjie.Bai
2042c7a6e5 fix: 云同步权限显示创建执行 2022-03-15 14:18:37 +08:00
Jiangjie.Bai
40aca26155 fix: 暂时排除会话分享的权限位 2022-03-15 13:13:16 +08:00
Jiangjie.Bai
e18e76002c fix: 暂时排除会话分享的权限位 2022-03-15 13:00:56 +08:00
Jiangjie.Bai
c77f02b295 Merge pull request #7844 from jumpserver/dev
v2.20.0-rc3
2022-03-15 11:37:30 +08:00
Jiangjie.Bai
3924ff0114 fix: 修改查看会话录像权限位 2022-03-15 11:37:09 +08:00
Jiangjie.Bai
6a0264ad3b fix: 删除权限位connect_myasset/myapp 2022-03-15 11:11:37 +08:00
Jiangjie.Bai
2d7349d596 fix: 删除权限位connect_myasset/myapp 2022-03-15 11:11:37 +08:00
feng626
c41a81c8d0 fix: 修改授权权限 2022-03-15 11:06:48 +08:00
feng626
7ba19ab1a1 fix: exclude adhoc change delete 2022-03-14 20:36:02 +08:00
Jiangjie.Bai
72247d1df3 fix: 修复批量命令权限 2022-03-14 20:35:43 +08:00
feng626
faf82d7cfb fix: del connect my asset 2022-03-14 20:34:35 +08:00
feng626
4e8defc647 fix: 修复上传bug 2022-03-14 19:15:12 +08:00
Jiangjie.Bai
2f18208874 fix: 修复资产改密计划权限控制 2022-03-14 19:01:26 +08:00
Jiangjie.Bai
b37e8cdc3f fix: 修复更新资产账号权限控制 2022-03-14 17:51:03 +08:00
Jiangjie.Bai
5b960fc46b fix: 修复测试资产账号权限 2022-03-14 17:51:03 +08:00
fit2bot
df51c82cfd perf: 优化Migration,删掉原来的 content type (#7835)
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-03-14 17:10:34 +08:00
feng626
e9deb6fc7a fix: app relation api 2022-03-14 17:05:47 +08:00
Jiangjie.Bai
cca49fa9cd fix: 修复授权树显示 2022-03-14 16:47:29 +08:00
Jiangjie.Bai
cfed849175 Merge pull request #7834 from jumpserver/dev
fix: 修复setting perm
2022-03-14 15:53:11 +08:00
feng626
a7cc457f54 fix: 修复setting perm 2022-03-14 15:50:53 +08:00
Jiangjie.Bai
5996cedcd6 Merge pull request #7832 from jumpserver/dev
fix: 修复权限问题
2022-03-14 15:16:51 +08:00
feng626
567c1b0124 fix: node test refresh perm 2022-03-14 14:37:59 +08:00
fit2bot
2da541c127 fix: 修改授权树(账号备份) (#7830)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-14 14:23:13 +08:00
jiangweidong
794139782f feat: JumpServer支持部署在使用了ssl的redis上,可使用证书连接 2022-03-14 11:35:14 +08:00
Jiangjie.Bai
307b739a03 fix: 修改授权树(收集用户) 2022-03-14 11:34:14 +08:00
feng626
ca5708988a fix: 修复saml2 auth 2022-03-14 11:17:15 +08:00
ibuler
90d84f4d69 perf: 修改消息订阅 2022-03-14 11:16:54 +08:00
feng626
758f418f63 perf: 删除多余权限 2022-03-14 10:48:04 +08:00
Jiangjie.Bai
a64ec8a1d2 Merge pull request #7825 from jumpserver/dev
v2.20.0-rc2
2022-03-14 10:38:35 +08:00
ibuler
60564d1b4f perf: 修改 bug 2022-03-14 10:01:51 +08:00
fit2bot
017710c056 perf: 修改perms (#7822)
* perf: 修改 perm tree

* perf: 修改perms

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-11 21:24:07 +08:00
Jiangjie.Bai
a876a82a76 fix: 从组织移除用户 2022-03-11 21:20:44 +08:00
Jiangjie.Bai
8423ae602f fix: 移除TICKET_ENABLED配置;系统设置API限制权限 2022-03-11 21:02:26 +08:00
Jiangjie.Bai
8e2471c1eb fix: 移除TICKET_ENABLED配置;系统设置API限制权限 2022-03-11 21:02:26 +08:00
Jiangjie.Bai
224a9fbdb3 fix: 修复创建授权时actions为空保存时报错的问题 2022-03-11 21:00:37 +08:00
ibuler
797b184c7f perf: 修改 perm tree 2022-03-11 20:31:38 +08:00
fit2bot
b3632f6531 fix: dingtalk auth perm (#7814)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 19:32:23 +08:00
fit2bot
e3bc54e764 fix: 修复用户组添加用户 (#7809)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 19:31:55 +08:00
fit2bot
f0325c48df fix: 工单权限 (#7808)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 19:31:29 +08:00
fit2bot
416d4bd0c3 fix: 修复tree (#7802)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 17:24:28 +08:00
fit2bot
10c877c120 fix: 修复工单ticket exclude perm (#7799)
* fix: 修复工单ticket exclude perm

* fix: 修复perm tree

Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 13:30:14 +08:00
jiangweidong
f04378eaf8 feat: JumpServer支持部署在使用了ssl的redis上 2022-03-11 12:56:22 +08:00
fit2bot
b644c47173 perf: 排除工单流权限 (#7798)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-11 11:04:21 +08:00
老广
45331dc9e8 Merge pull request #7796 from jumpserver/dev
v2.20.0-rc1
2022-03-10 20:34:18 +08:00
ibuler
8a565b9eef perf: 修改设置 2022-03-10 20:30:41 +08:00
ibuler
4eb7b50b52 perf: 修改设置 2022-03-10 20:30:41 +08:00
Jiangjie.Bai
fd64bd03b4 fix: 修改LDAP配置API权限 2022-03-10 19:03:51 +08:00
Jiangjie.Bai
9c75147179 fix: 修改LDAP配置API权限 2022-03-10 19:03:51 +08:00
fit2bot
147e4cce94 perf: 修改 migrations (#7794)
* perf: 优化 auditor 权限

* perf: 修改 migrations

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-10 18:55:53 +08:00
fit2bot
d1e25e1fef fix: 删除应用/授权应用相关权限 (#7792)
* fix: 删除应用/授权应用相关权限

* fix: 删rbac清除code的一些迁移文件;增加到utils目录下

Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-10 18:51:45 +08:00
fit2bot
af2ba07338 fix: exclude (#7791)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-10 18:11:33 +08:00
fit2bot
29b9adb684 perf: 修复一把数据 (#7789)
* fix: 优化 perm exclude

* perf: 修复一把数据

perf: 修复一些数据

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-10 17:40:31 +08:00
fit2bot
64e0860d24 fix: 修复app suggestion perm bug (#7788)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-10 17:24:24 +08:00
ibuler
9934007397 fix: 优化 perm exclude 2022-03-10 16:56:32 +08:00
Jiangjie.Bai
4044a71aea revert: 回滚权限树 2022-03-10 15:27:15 +08:00
fit2bot
9725f0c963 fix: 修复工单流500bug (#7784)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-10 11:26:34 +08:00
Jiangjie.Bai
b017e68a56 Perf: 优化RBAC权限树 (#7782)
* fix: 优化权限树(1)

* fix: 优化权限树(2)

* fix: 优化权限树(3)

* fix: 优化权限树(4)

* fix: 优化权限树(5)

* fix: 优化权限树(添加迁移文件)

* fix: 优化权限树(6)

* fix: 优化权限树(7)

* fix: 优化权限树(8)

* fix: 优化权限树(9)
2022-03-10 11:25:33 +08:00
fit2bot
9ca0eaf7ce fix: 修改校对资产数量permbug (#7777)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-09 15:01:44 +08:00
fit2bot
94e60e180e fix: 修复新建组织用户列表获取到是全局用户bug (#7776)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-09 11:17:28 +08:00
fit2bot
8ed221ea5a fix: org role perm (#7775)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-08 20:22:10 +08:00
fit2bot
42ebb1f82f fix: 删除组织角色时 判断全局绑定用户数量 (#7774)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-08 20:00:19 +08:00
ibuler
9492518773 perf: 修改 redis conn 2022-03-08 18:49:50 +08:00
feng626
1cca9c10fb perf: 修改perm判断逻辑 2022-03-08 18:41:50 +08:00
feng626
c4a6715eb8 fix: 命令存储 or 命令权限 2022-03-08 17:43:26 +08:00
ibuler
4c31b5ec0f perf: 去掉一些 perm 2022-03-08 17:33:06 +08:00
fit2bot
9fd7fa9339 fix: add auditor perm (#7768)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-08 15:53:02 +08:00
feng626
a930f3aab3 fix: 修复创建更新用户给定默认权限 2022-03-08 14:07:02 +08:00
ibuler
5081fb5fe7 perf: 优化perm tree, 并添加缓存 2022-03-08 13:46:25 +08:00
fit2bot
cb072123d6 fix: 修复org admin ticket flow perm (#7765)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-08 12:42:46 +08:00
fit2bot
761265dec5 fix: 修复index api perm (#7761)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-08 10:43:01 +08:00
fit2bot
89de111acc fix: 修复特殊用户过滤 (#7759)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-07 20:09:52 +08:00
ibuler
14327ee398 perf: 优化账号备份api path 2022-03-07 19:56:27 +08:00
fit2bot
1b007c8c5c perf: 修改权限树 (#7757)
* perf: 修改 rbac tree

* perf: 修改权限树

* perf:  修改用户默认权限

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-07 19:02:37 +08:00
fit2bot
3222687aaa fix: 修复应用授权权限bug (#7756)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-07 18:42:22 +08:00
feng626
79994f5ddc fix: 资产授权权限bug 2022-03-07 18:25:06 +08:00
fit2bot
8271492ec1 fix: 修复查看资产密钥bug (#7754)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-07 17:55:35 +08:00
fit2bot
27560793f8 fix: 修复系统用户任务权限bug (#7753)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-07 16:01:02 +08:00
Jiangjie.Bai
615929dd43 fix: 修复可以删除已关联用户角色的问题 2022-03-07 15:05:58 +08:00
feng626
a1c1b128e9 fix: 修复relation_systemuser_perm问题 2022-03-07 14:53:38 +08:00
ibuler
fa2c70c6be perf: 修改 perm node title 2022-03-07 14:39:07 +08:00
Jiangjie.Bai
46e119db1f fix: 后台不限制roles的必填项 2022-03-07 13:56:13 +08:00
ibuler
0afff45bae fix: validate app perm error 2022-03-07 11:42:39 +08:00
fit2bot
31d219524b fix: 修复创建用户roles必填问题 (#7745)
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-07 11:21:25 +08:00
fit2bot
a20884e2ad perf: 修改 rbac tree (#7743)
* perf: 修改 rbac tree

* perf: 修改verbose name

* fix: 修复系统用户

* fix: 还原 xpack

Co-authored-by: ibuler <ibuler@qq.com>
2022-03-07 11:19:03 +08:00
feng626
eb6bddc599 fix: 拆分角色权限树router 2022-03-04 18:13:59 +08:00
Jiangjie.Bai
8a8ed90eef fix: 保留之前的jms_oidc_rp包 2022-03-04 18:12:46 +08:00
Jiangjie.Bai
75825f5baa fix: 删除jms_oidc_rp包中的表jms_oidc_rp_oidcuser 2022-03-04 18:12:46 +08:00
fit2bot
0141fce27d fix: 审计员add工作台 (#7738)
Co-authored-by: feng626 <1304903146@qq.com>
2022-03-04 10:46:45 +08:00
老广
3f9f9351f3 Fix rbac (#7737)
* perf: 修改 rbac role bingding

* fix: suggestion perm

* perf: 修改 requirements

* perf: 修改 rbac

* fix: auditor_perms

Co-authored-by: feng626 <1304903146@qq.com>
2022-03-04 10:16:21 +08:00
ibuler
390b8693df perf: 修改 signal handler 2022-03-03 10:03:06 +08:00
fit2bot
dafc416783 Fix rbac (#7728)
* perf: 重命名 signal handlers

* fix: 修复 ticket processor 问题

* perf: 修改 ticket 处理人api

* fix: 修复创建系统账号bug

* fix: 升级celery_beat==2.2.1和flower==1.0.0;修改celery进程启动参数先后顺序

* perf: 修改 authentication token

* fix: 修复上传权限bug

* fix: 登录页面增加i18n切换;

* fix: 系统角色删除限制

* perf: 修改一下 permissions tree

* perf: 生成 i18n

* perf: 修改一点点

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
2022-03-02 20:48:43 +08:00
halo
04e46e4b1c fix: 修复节点创建不能指定id问题,兼容api 2022-03-02 16:24:03 +08:00
fit2bot
ab1024fbf4 perf: 优化 super ticket 的状态 (#7714)
* fix: token 系统用户增加 protocol

* fix: 修复清除orphan session时同时清除对应的 session_task

* perf: 修改 connection token api

* fix: 修复无法获取系统角色绑定的问题

* perf: 增加 db terminal 及 magnus 组件

* perf: 修改 migrations

* fix: 修复AUTHENTICATION_BACKENDS相关的逻辑

* fix: 修改判断backend认证逻辑

* fix: 修复资产账号查看密码跳过mfa

* fix: 修复用户组授权权限错误

* feat: 支持COS对象存储

* feat: 升级依赖 jms_storage==0.0.42

* fix: 修复 koko api 问题

* feat: 修改存储翻译信息

* perf: 修改 ticket 权限

* fix: 修复获取资产授权系统用户 get_queryset

* perf: 抽取 ticket

* perf: 修改 cmd filter 的权限

* fix: 修改 ticket perm

* perf: 修改工单的api

Co-authored-by: Eric <xplzv@126.com>
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: 小冯 <xiaofeng@xiaofengdeMacBook-Pro.local>
Co-authored-by: feng626 <1304903146@qq.com>
2022-02-28 20:22:14 +08:00
Jiangjie.Bai
03afa4f974 Fix rbac (#7713)
* fix: token 系统用户增加 protocol

* fix: 修复清除orphan session时同时清除对应的 session_task

* perf: 修改 connection token api

* fix: 修复无法获取系统角色绑定的问题

* perf: 增加 db terminal 及 magnus 组件

* perf: 修改 migrations

* fix: 修复AUTHENTICATION_BACKENDS相关的逻辑

* fix: 修改判断backend认证逻辑

* fix: 修复资产账号查看密码跳过mfa

* fix: 修复用户组授权权限错误

* feat: 支持COS对象存储

* feat: 升级依赖 jms_storage==0.0.42

* fix: 修复 koko api 问题

* feat: 修改存储翻译信息

* perf: 修改 ticket 权限

* fix: 修复获取资产授权系统用户 get_queryset

* perf: 抽取 ticket

* perf: 修改 cmd filter 的权限

* fix: 修改 ticket perm

* fix: 修复oidc依赖问题

Co-authored-by: Eric <xplzv@126.com>
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: 小冯 <xiaofeng@xiaofengdeMacBook-Pro.local>
Co-authored-by: feng626 <1304903146@qq.com>
2022-02-28 19:28:58 +08:00
Jiangjie.Bai
edfca5eb24 Fix rbac (#7699)
* perf: 优化 suggesstion

* perf: 修改 migrations

* feat: 添加OIDC认证逻辑

* perf: 修改 backend

* perf: 优化认证backends

* perf: 优化认证backends

* perf: 优化CAS认证, 用户多域名进行访问时回调到各自域名

Co-authored-by: ibuler <ibuler@qq.com>
2022-02-25 19:23:59 +08:00
老广
02ca473492 Fix rbac (#7690)
* perf: 优化 suggesstion

* perf: 修改 migrations
2022-02-24 12:03:40 +08:00
老广
484b75bb53 Merge pull request #7687 from jumpserver/fix_rbac
fix: rbac
2022-02-24 10:06:47 +08:00
xinwen
9c3fd59ef4 fix: 删除用户最近登录的资产接口 2022-02-23 18:35:53 +08:00
feng626
bbf3250161 fix: 优化用户列表接口性能 2022-02-23 18:35:10 +08:00
feng626
8604b9019f fix: 添加迁移文件 2022-02-23 18:32:30 +08:00
Jiangjie.Bai
966b4250b8 Merge branch 'fix_rbac' of github.com:jumpserver/jumpserver into fix_rbac 2022-02-23 18:28:47 +08:00
Jiangjie.Bai
291f2b0e13 fix: 修复用户列表出现服务账号的问题 2022-02-23 18:28:23 +08:00
Eric
a1d15ef206 fix: 修复管理员终断会话API 2022-02-23 17:10:02 +08:00
ibuler
e76eec530f perf: 添加migrations 2022-02-23 17:06:07 +08:00
ibuler
add4d8d2cd fix: 修改上传录像 api 权限 2022-02-23 15:47:12 +08:00
ibuler
c6ece550a9 perf: 修改翻译 2022-02-22 19:53:00 +08:00
xinwen
e3b620089a feat: 个人页面接口 2022-02-22 18:29:49 +08:00
Jiangjie.Bai
64f721875b fix: 修复用户页面点击资产树节点提示对象找不到的问题 2022-02-22 18:29:49 +08:00
ibuler
02d3747c70 perf: 添加监测密码的脚本 2022-02-22 18:29:49 +08:00
feng626
09494193ab fix: 修复批量操作权限bug 2022-02-22 18:29:49 +08:00
feng626
702111f578 fix: 修复系统用户sudo tab权限 2022-02-22 18:29:49 +08:00
feng626
e08db7423f fix: 修复资产账号测试可连接性权限问题 2022-02-22 18:29:49 +08:00
ibuler
0c95faac04 fix: 修复 cache set 2022-02-22 18:29:49 +08:00
fit2bot
534cbf1281 perf: 修改依赖版本 (#7666)
* perf: 修复一些错误权限位

* Pr@fix rbac@fix rbac permissions (#7648)

* fix: 确保每次 migrate 执行更新 role permissions

* perf: 修改 choices

* feat: 兼容apple m1

* perf: 修改 migrations role permissions

* perf: pymysql 导入

* perf: admin 判断

* perf: 修改依赖版本

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
2022-02-22 18:29:49 +08:00
fit2bot
abe5fa9036 perf: 修改依赖库版本 (#7661)
* perf: 修复一些错误权限位

* Pr@fix rbac@fix rbac permissions (#7648)

* fix: 确保每次 migrate 执行更新 role permissions

* perf: 修改 choices

* feat: 兼容apple m1

* perf: 修改 migrations role permissions

* perf: pymysql 导入

* perf: admin 判断

* perf: 修改依赖库版本

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
2022-02-22 18:29:49 +08:00
feng626
2a2f05e51c fix: 删除组织关联删除工单 工单流 2022-02-22 18:29:49 +08:00
xinwen
f460916e84 fix: swagger 2022-02-22 18:29:49 +08:00
jiangweidong
ad2cb233d7 feat: 支持 MongoDB 数据库的纳管 (#7631) 2022-02-22 10:09:48 +08:00
halo
0dbf035146 perf: 优化代码 2022-02-21 16:52:21 +08:00
halo
ea124fd0db fix: 修复keycloak配置转换为openid不生效问题,持久化到数据库 2022-02-21 16:52:21 +08:00
Jiangjie.Bai
83ff8dbf26 fix: rbac 合并 (#7658)
* perf: 修复一些错误权限位

* Pr@fix rbac@fix rbac permissions (#7648)

* fix: 确保每次 migrate 执行更新 role permissions

* perf: 修改 choices

* feat: 兼容apple m1

* perf: 修改 migrations role permissions

* perf: pymysql 导入

* perf: admin 判断

* fix: 修复消息订阅权限

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
Co-authored-by: feng626 <1304903146@qq.com>
2022-02-21 16:24:03 +08:00
Jiangjie.Bai
783c163324 fix: 修复获取命令过滤规则时按照有组织的资源进行组织过滤 2022-02-19 11:44:03 +08:00
Jiangjie.Bai
3deced4ade fix: 修复登录系统用户temp_auth保存时构建的key和获取时不一致的问题 2022-02-18 20:07:19 +08:00
fit2bot
63de4e1806 perf: 添加 is_org_admin (#7644)
* fix: 修复 org members 的问题

* perf: 修改 org member

* perf: 修改 is sa

* perf: 修改 active

* perf: 修复写法

* perf: is_sa to is_service_account

Co-authored-by: ibuler <ibuler@qq.com>
2022-02-18 16:25:54 +08:00
ibuler
48d0c7b6cc fix: 修复 org members 的问题 2022-02-18 14:37:38 +08:00
ibuler
20cc8a124f perf: 修改connection token domain
perf: 添加 org_id
2022-02-18 14:10:22 +08:00
ibuler
db050e405d fix: 修改 migrations 2022-02-17 23:02:32 +08:00
fit2bot
e259d2a9e9 fix: fix rbac to dev (#7636)
* feat: 添加 RBAC 应用模块

* feat: 添加 RBAC Model、API

* feat: 添加 RBAC Model、API 2

* feat: 添加 RBAC Model、API 3

* feat: 添加 RBAC Model、API 4

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC 整理权限位

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位

* feat: RBAC 添加默认角色

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 修改用户模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 修改用户角色属性的使用

* feat: RBAC No.1

* xxx

* perf: 暂存

* perf: ...

* perf(rbac): 添加 perms 到 profile serializer 中

* stash

* perf: 使用init

* perf: 修改migrations

* perf: rbac

* stash

* stash

* pref: 修改rbac

* stash it

* stash: 先去修复其他bug

* perf: 修改 role 添加 users

* pref: 修改 RBAC Model

* feat: 添加权限的 tree api

* stash: 暂存一下

* stash: 暂存一下

* perf: 修改 model verbose name

* feat: 添加model各种 verbose name

* perf: 生成 migrations

* perf: 优化权限位

* perf: 添加迁移脚本

* feat: 添加组织角色迁移

* perf: 添加迁移脚本

* stash

* perf: 添加migrateion

* perf: 暂存一下

* perf: 修改rbac

* perf: stash it

* fix: 迁移冲突

* fix: 迁移冲突

* perf: 暂存一下

* perf: 修改 rbac 逻辑

* stash: 暂存一下

* perf: 修改内置角色

* perf: 解决 root 组织的问题

* perf: stash it

* perf: 优化 rbac

* perf: 优化 rolebinding 处理

* perf: 完成用户离开组织的问题

* perf: 暂存一下

* perf: 修改翻译

* perf: 去掉了 IsSuperUser

* perf: IsAppUser 去掉完成

* perf: 修改 connection token 的权限

* perf: 去掉导入的问题

* perf: perms define 格式,修改 app 用户 的全新啊

* perf: 修改 permission

* perf: 去掉一些 org admin

* perf: 去掉部分 org admin

* perf: 再去掉点 org admin role

* perf: 再去掉部分 org admin

* perf: user 角色搜索

* perf: 去掉很多 js

* perf: 添加权限位

* perf: 修改权限

* perf: 去掉一个 todo

* merge: with dev

* fix: 修复冲突

Co-authored-by: Bai <bugatti_it@163.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
Co-authored-by: ibuler <ibuler@qq.com>
2022-02-17 20:13:31 +08:00
Jiangjie.Bai
18c388f3a5 Merge pull request #7629 from jumpserver/dev
v2.19.0-rc3
2022-02-17 11:04:33 +08:00
feng626
b088362ae3 perf: 账号备份性能优化 2022-02-17 11:02:49 +08:00
xinwen
c7f8ebb613 fix: 站内信 ServerPerformanceCheck redis 订阅报错 2022-02-17 10:53:36 +08:00
feng626
de2f9ae687 Merge pull request #7626 from jumpserver/pr@dev@fix_i18n
fix: 翻译
2022-02-16 19:19:55 +08:00
xinwen
a806a2d3e6 fix: 翻译 2022-02-16 19:16:45 +08:00
Jiangjie.Bai
7be76feeb0 Merge pull request #7622 from jumpserver/dev
v2.19.0-rc3
2022-02-16 16:42:19 +08:00
ibuler
f548abcb87 perf: 用户临时密码支持加密传输 2022-02-16 16:31:57 +08:00
xinwen
35c6b581e2 feat: 远程应用支持磁盘挂载 2022-02-16 16:29:06 +08:00
feng626
40b119786b Merge pull request #7621 from jumpserver/pr@dev@ticket_flow
fix: 工单流需要超级管理员配置
2022-02-16 14:47:56 +08:00
feng626
ff9347e344 fix: 工单流需要超级管理员配置 2022-02-16 14:37:26 +08:00
feng626
da0bbcee57 fix: 修复资产账号过滤重复问题 2022-02-16 11:35:53 +08:00
ibuler
824d10ce93 pref: connection token 添加 secret 2022-02-16 11:33:25 +08:00
feng626
1d6dcf9fb5 fix: 修复命令报警翻译 2022-02-15 18:33:52 +08:00
Jiangjie.Bai
3325867f8f fix: 修改LDAP SYNC相关参数设置 2022-02-15 17:57:56 +08:00
xinwen
2f43aeee5d fix: Authbook 修改秘钥不生效 2022-02-15 11:14:51 +08:00
Jiangjie.Bai
764d70ea4f fix: 修改用户组名称翻译 2022-02-14 19:27:41 +08:00
Jiangjie.Bai
ff6dbe67a6 Merge pull request #7610 from jumpserver/dev
v2.19.0-rc2
2022-02-14 18:31:52 +08:00
feng626
7f36958683 perf: 工单流只需组织管理员权限 2022-02-14 18:15:11 +08:00
xinwen
fa5921cd86 fix: 去掉 can_replay 兼容代码 2022-02-14 18:14:37 +08:00
feng626
540679df11 fix: 修复operatelog add remove 翻译问题 2022-02-14 14:04:59 +08:00
fit2bot
597b022905 fix: 修复历史会话文件不能被清理的bug (#7604)
* fix: 修复历史会话文件不能被清理的bug

* perf: 删除调试日志

Co-authored-by: halo <wuyihuangw@gmail.com>
2022-02-14 10:58:30 +08:00
jiangweidong
ab34b9906e perf: 切割一次就可以了 2022-02-10 18:34:09 +08:00
jiangweidong
755fa8efa8 perf: 兼容不同版本间JumpServer获取的SAML2协议用户属性 2022-02-10 18:34:09 +08:00
feng626
889713f00e fix: 修复工单流程设置显示其它组织问题 2022-02-10 14:07:32 +08:00
Jiangjie.Bai
c10436de47 Merge pull request #7589 from jumpserver/dev
v2.19.0-rc1
2022-02-10 11:24:28 +08:00
xinwen
333bb64b8b fix: Authbook 取认证信息bug 2022-02-10 11:20:40 +08:00
Michael Bai
67a49dc5e9 feat: syslog 记录的数据来源于序列类 2022-02-08 19:22:08 +08:00
Michael Bai
8085db7acc feat: 增加系统设置(安全)控制第三方认证用户是否进行MFA认证 2022-02-08 17:48:40 +08:00
Michael Bai
6adeafd1d2 fix: 修复创建命令过滤规则失败的问题 2022-02-08 14:21:43 +08:00
xinwen
1faba95a48 fix: 修复 xrdp 连接资产时会生成用户登录日志 2022-02-08 12:38:27 +08:00
吴小白
ab07091eb8 perf: 优化 quick_start.sh 2022-02-08 12:36:43 +08:00
xinwen
f994f5d776 fix: redis 订阅 bug 2022-02-08 12:35:16 +08:00
ibuler
55fae1667d fix: 修复 redis 连接过多的问题 2022-02-08 12:35:16 +08:00
Michael Bai
b3397c6aeb feat: 命令过滤规则增加忽略大小写选项 2022-02-08 12:31:15 +08:00
老广
8ab4f6f004 docs: 添加 pr 提示说明 2022-02-07 15:39:50 +08:00
老广
5a37540eda docs: 修改贡献提示 2022-02-07 15:39:50 +08:00
老广
1c1d507e34 Create CONTRIBUTING.md 2022-02-07 15:39:50 +08:00
老广
9c40314edc Create CODE_OF_CONDUCT.md 2022-02-07 15:39:22 +08:00
feng626
acdde5a236 fix: 密钥密码翻译 2022-01-27 18:19:44 +08:00
Jiangjie.Bai
37a3566b0e Merge pull request #7540 from jumpserver/dev
v2.18
2022-01-20 13:47:13 +08:00
feng626
a81f6bf97b fix: 应用账号attrs字段问题 2022-01-20 13:20:45 +08:00
Michael Bai
b07f532a71 fix: 修复导出应用账号会包含attrs字段的问题 2022-01-20 12:00:18 +08:00
feng626
46270fd91c fix: authbook load asset queryset bug 2022-01-20 11:03:18 +08:00
Jiangjie.Bai
2b364c1476 Merge pull request #7534 from jumpserver/dev
v2.18.0-rc4
2022-01-19 19:36:59 +08:00
feng626
9e47bf6ec5 fix: 批量命令bug 2022-01-19 19:34:32 +08:00
ibuler
89c7e514eb perf: 修复登录和推送系统用户是密码选择 2022-01-19 19:08:38 +08:00
feng626
83c5344307 fix: 获取命令规则过滤不准 2022-01-19 19:07:43 +08:00
feng626
2beec1a03b Merge pull request #7530 from jumpserver/pr@dev@ssh_passphrase_bug
fix: 修改 修改ssh密钥时报500问题
2022-01-19 11:11:49 +08:00
feng626
d53925d1fb Merge pull request #7529 from jumpserver/pr@dev@ticket_bug
fix: 修复工单审批后审批人与记录人不一致问题
2022-01-19 11:11:34 +08:00
feng626
69d4a0a250 fix: 修改 修改ssh密钥时报500问题 2022-01-19 10:39:17 +08:00
feng626
e33a67daf6 fix: 修复工单审批后审批人与记录人不一致问题 2022-01-19 10:33:41 +08:00
Jiangjie.Bai
2036037675 Merge pull request #7527 from jumpserver/dev
v2.18.0-rc3
2022-01-18 19:35:37 +08:00
fit2bot
0b16d70c0c fix: 修改翻译 (#7526)
* fix: 修改翻译

* fix: 修改保存数据库翻译

* fix: 修复翻译为none问题

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-01-18 19:31:01 +08:00
Michael Bai
8d6498c8f0 fix: 升级依赖 jms-storage==0.0.41 2022-01-18 17:01:02 +08:00
Michael Bai
59d0f53725 fix: 修改审计日志操作日志动作翻译问题 2022-01-18 15:21:35 +08:00
Michael Bai
518caa4f7a fix: 修改应用账号APP名称的VerboseName 2022-01-18 15:03:23 +08:00
Michael Bai
b8aaa7d249 fix: 修改命令过滤器翻译 2022-01-18 14:27:22 +08:00
Michael Bai
c9f63a3f4a fix: 修改审计日志中的i18n翻译问题 2022-01-18 13:21:31 +08:00
xinwen
ec68fc9562 fix: 绑定三方登录消息翻译 2022-01-18 10:39:35 +08:00
xinwen
561ce53413 fix: 空的 es 存储,指定 timestamp 排序报错 2022-01-18 10:14:51 +08:00
Jiangjie.Bai
6bd597eadd Merge pull request #7511 from jumpserver/dev
v2.18.0-rc2
2022-01-17 19:21:39 +08:00
feng626
005032ea00 fix: 修复账号备份存在外键search 500 bug 2022-01-17 19:21:13 +08:00
Michael Bai
de74477fd6 fix: 修改翻译文件 2022-01-17 19:11:01 +08:00
fit2bot
c43ad981bd perf: 优化写法 (#7498)
* fix: 修复登录页输入 mfa 时不支持 某 mfa 的错误提示

fix tapd 1145454465001008371

* perf: 优化 send code api,避免暴力常识

* perf: 优化写法

* Update mfa.py

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2022-01-17 19:05:01 +08:00
xinwen
088676d998 fix: 计算工单序号的时候切换到root组织 2022-01-17 16:22:04 +08:00
jiangweidong
106bb9b63d perf: SAML2属性映射去掉域名前缀 2022-01-17 16:06:37 +08:00
ibuler
451e61bb61 perf: 优化 celery 任务中的数据库连接问题
perf: add comment
2022-01-17 16:04:50 +08:00
halo
e1de210585 feat: 创建用户邮件内容支持html标签 2022-01-17 16:03:04 +08:00
xinwen
cce34f4939 fix: 用户登录失败时,登陆日志中的认证方式不准确 2022-01-17 16:02:28 +08:00
fit2bot
def9bedd30 perf: 账号备份优化 (#7503)
* perf: 账号备份优化

* feat: 优化账号备份获取有序备份字段列表

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2022-01-17 15:58:39 +08:00
feng626
d2b3edffca Merge pull request #7505 from jumpserver/pr@dev@ticket_bug
fix: 修复工单审批后state不准问题
2022-01-17 15:51:49 +08:00
Michael Bai
aea2db84e8 fix: 添加deb依赖: libaio-dev freetds-dev 2022-01-17 13:57:08 +08:00
feng626
6a4ffcc9ad fix: 修复工单审批后state不准问题 2022-01-16 17:49:17 +08:00
fit2bot
4343b6487d fix: 修复登录页输入 mfa 时不支持 某 mfa 的错误提示 (#7495)
* fix: 修复登录页输入 mfa 时不支持 某 mfa 的错误提示

fix tapd 1145454465001008371

* perf: 优化 send code api,避免暴力常识

Co-authored-by: ibuler <ibuler@qq.com>
2022-01-13 19:01:12 +08:00
Michael Bai
ba695c4600 fix: 抽象permissions-serializer的actions字段值设置 2022-01-13 18:58:10 +08:00
Michael Bai
21a34ddc03 feat: 返回License信息 2022-01-13 18:55:44 +08:00
ibuler
145c7952c9 perf: 优化 ops 任务,支持 i18n
- 内置任务名称支持了 i18n,数据库存英文,返回是翻译一下
- 任务执行中,添加 language 上下文
2022-01-13 15:03:48 +08:00
xinwen
43c4c78378 fix: 工单序号添加排序 2022-01-13 14:37:02 +08:00
Michael Bai
620834c817 fix: 修改工单迁移文件warining问题
Any fields that are stored with VARCHAR column types may have their max_length restricted to 255 characters if you are using unique=True for the field.
See: https://docs.djangoproject.com/en/3.1/ref/databases/#mysql-character-fields
2022-01-13 14:36:30 +08:00
Jiangjie.Bai
fbd0b44d4f Merge pull request #7490 from jumpserver/dev
v2.18.0-rc1
2022-01-12 20:58:04 +08:00
xinwen
4b44a54d97 fix: 腾讯验证码测试不通过 2022-01-12 20:57:22 +08:00
Eric
6716acb4ff perf: 更新安全英文版本 2022-01-12 20:56:58 +08:00
Jiangjie.Bai
35722a8466 Merge pull request #7487 from jumpserver/dev
v2.18.0-rc1
2022-01-12 20:56:33 +08:00
feng626
e5659a1d07 fix: 修复翻译及迁移文件 2022-01-12 20:55:58 +08:00
xinwen
414137cd73 fix: 三方认证绑定发通知文案 2022-01-12 20:34:19 +08:00
xinwen
1e3a15a3d0 feat: 三方认证绑定发通知 2022-01-12 20:23:25 +08:00
ibuler
dde7559f47 feat: node api 支持使用 full_value 递归创建 2022-01-12 20:23:16 +08:00
feng626
b0932e5137 feat: 逃生通道 2022-01-12 20:22:36 +08:00
xinwen
5cdc4c3c28 feat: 工单添加序号 2022-01-12 10:38:07 +08:00
ibuler
25a2290804 perf: 优化迁移数据库错误提示 2022-01-10 17:32:01 +08:00
Michael Bai
4405abbedf feat: 2022 2022-01-04 12:54:12 +08:00
halo
3f6c9d519e fix: 修复通知用户过期时间bug 2021-12-31 17:26:23 +08:00
xinwen
bd84edea62 feat: 资产登录工单页面增加监控与中断 2021-12-31 17:23:39 +08:00
feng626
100bfe0304 feat: 新增获取k8s pod namespace container接口 2021-12-31 15:54:59 +08:00
feng626
11fd9a6567 feat: 配置私钥密码 2021-12-31 14:47:01 +08:00
Michael Bai
90299a508c fix: 授权actions serializer 设置default值 2021-12-30 17:25:00 +08:00
Michael Bai
de9516dee5 feat: 应用授权增加Action动作控制 2021-12-30 14:47:58 +08:00
jiangweidong
db01a6d48d fix: 因为admin_user表中有历史数据,导致组织无法删除 2021-12-30 10:48:07 +08:00
halo
c2d271f00b feat: rdp协议新增username表达式,匹配更多特殊字符 2021-12-30 10:01:26 +08:00
halo
90de229631 feat: rdp协议username支持输入中文和$ 2021-12-30 10:01:26 +08:00
xinwen
35a10fdd62 feat: 命令记录接口增加 remote_addr 字段 2021-12-28 18:26:21 +08:00
xinwen
89cad224c5 fix: SSO 限制用户删除 2021-12-28 18:24:32 +08:00
jiangweidong
9b2e1e08d8 feat: 将redis_acl协议合并到redis协议中 2021-12-28 18:15:00 +08:00
jiangweidong
aaaa87dd60 feat: 增加数据库redis的纳管功能 2021-12-28 18:15:00 +08:00
吴小白
24cad76232 perf: 更新基础镜像 2021-12-28 18:12:10 +08:00
吴小白
040f1fcbb8 perf: 添加 quick_start.sh 2021-12-27 12:32:58 +08:00
Eric
d76ef788d2 perf: 修改 Jmservisor 的下载地址名称 2021-12-24 11:35:47 +08:00
feng626
38c870a0b5 perf: 工单流对应受理人懒加载 2021-12-21 18:20:02 +08:00
Michael Bai
ac9e7e9b40 fix: 下载页面添加Jmservisor拉起脚本 2021-12-17 15:54:32 +08:00
Michael Bai
5aed04d58b fix: 修改SAML2.0 Logo 2021-12-17 15:25:15 +08:00
jiangweidong
c05951b6c4 feat: 添加数据库SQLServer改密功能的python依赖库 2021-12-17 11:20:09 +08:00
ibuler
107215aadc workflow: 添加同步 gitee 的 workflow 2021-12-17 11:19:47 +08:00
Jiangjie.Bai
d27947919b Merge pull request #7404 from jumpserver/dev
v2.17.0 rc4
2021-12-15 22:03:19 +08:00
ibuler
b92530f0b9 perf: 优化通知,对支持 markdown 的发 markdown 2021-12-15 20:58:33 +08:00
ibuler
b113eeb1d6 perf: 修复基本设置中的 base_site 可能带 / 的问题 2021-12-15 20:55:06 +08:00
ibuler
eb3165f8e7 perf: 优化 saml 2021-12-15 20:54:34 +08:00
xinwen
93d77b2312 fix: 执行 ansible 任务日志记录错误 2021-12-15 18:02:14 +08:00
Michael Bai
ae1d419f70 fix: 修复用户组命令过滤规则获取不到的问题 2021-12-15 16:34:33 +08:00
feng626
36054cb64c Merge pull request #7397 from jumpserver/pr@dev@translate
feat: translate
2021-12-15 16:21:52 +08:00
feng626
022e93d7a2 feat: translate 2021-12-15 16:15:21 +08:00
Michael Bai
ac14790960 fix: 修改命令过滤规则动作允许值1->9 2021-12-15 14:57:44 +08:00
feng626
facc231e3f Merge pull request #7394 from jumpserver/pr@dev@ticket_filter_bug
perf: ticket filter
2021-12-15 14:40:28 +08:00
feng626
e4178849ba perf: ticket filter 2021-12-15 14:23:07 +08:00
Jiangjie.Bai
151d897746 Merge pull request #7391 from jumpserver/dev
v2.17.0 rc3
2021-12-14 21:58:27 +08:00
xinwen
27588f48d8 fix: authbook 创建的时候没有自动推送 2021-12-14 20:07:16 +08:00
Michael Bai
303102d40b fix: 删除一些启动时大量输出的debug日志 2021-12-14 20:06:49 +08:00
xinwen
ff9632d6da fix: LDAP 测试连接报错 2021-12-14 20:04:41 +08:00
Michael Bai
4cbf6dd5e6 fix: 修复获取系统用户认证信息API 2021-12-14 19:12:22 +08:00
xinwen
4f889cfe36 fix: 带 ad_domain 的系统用户不应该支持推送 2021-12-14 18:05:34 +08:00
ibuler
0c2e5f3f2a perf: 优化 saml2 i18n 2021-12-14 18:01:08 +08:00
ibuler
19ecc7fef6 fix: 修复 otp 返回时报错 2021-12-14 17:50:33 +08:00
ibuler
0020343ae0 perf: 优化运行的命名 2021-12-14 17:47:10 +08:00
ibuler
fa5c433c7c perf: 优化启动脚本,避免启动超时 2021-12-14 17:47:10 +08:00
jiangweidong
5139f9c4b9 feat: saml2认证支持https协议 2021-12-14 17:12:43 +08:00
Jiangjie.Bai
d6aad41d05 Merge pull request #7373 from jumpserver/dev
v2.17.0 rc2
2021-12-13 19:47:33 +08:00
xinwen
b3acc0d451 fix: 去掉 get_docker_mem_usage_if_limit 日志 2021-12-13 18:09:55 +08:00
ibuler
330917df4c fix: 修复 saml2 登陆的问题 2021-12-13 17:52:18 +08:00
ibuler
21d4ffa33b perf: 优化 cas 回调地址翻译 2021-12-13 16:33:00 +08:00
xinwen
1bc14c53d4 fix: 企业微信发送报错 2021-12-13 16:32:09 +08:00
ibuler
5024d0d739 perf: 优化 saml2 log 2021-12-13 16:30:38 +08:00
jiangweidong
c5013dcbd6 feat: saml2协议单点登录支持在页面上配置saml2协议的高级配置 (#7362) 2021-12-13 10:54:14 +08:00
halo
84924bc3f6 fix: 修复会话详情页命令列表排序失效bug 2021-12-13 10:52:37 +08:00
Michael Bai
2de769ecad chore: 修改依赖版本: jms-storage==0.0.40 2021-12-13 10:47:09 +08:00
feng626
ab68aed98f Merge pull request #7363 from jumpserver/pr@dev@ticket_bug
perf: 工单根据选择组织自动选择流
2021-12-13 10:25:48 +08:00
feng626
9b9e32d2f4 perf: 工单根据选择组织自动选择流 2021-12-11 12:50:30 +08:00
ibuler
b6249e9a63 fix: 修复登录时跳转问题 2021-12-10 17:49:29 +08:00
Jiangjie.Bai
5f7fa7e02f Merge pull request #7355 from jumpserver/dev
v2.17.0 rc1
2021-12-09 20:57:02 +08:00
Michael Bai
74fe9dddb7 fix: 修改i18n 2021-12-09 20:35:52 +08:00
ibuler
ade3f3ae6c fix: 修复需要设置 mfa 的 bug 2021-12-09 20:24:02 +08:00
Michael Bai
1c3b574c46 fix: 修复系统用户命令过滤规则必填的问题 2021-12-09 20:23:26 +08:00
Michael Bai
92aeae4a2a fix: 修改i18n
fix: 修改i18n
2021-12-09 20:23:07 +08:00
xinwen
ea6c28fa0d fix: 修改 cgroup memory log 2021-12-09 20:22:34 +08:00
fit2bot
f44acc923b perf: 修改 otp 的显示,避免误会 (#7345)
perf: 还是用 OTP 吧

Co-authored-by: ibuler <ibuler@qq.com>
2021-12-09 19:33:11 +08:00
ibuler
f27df2f523 fix: 修复 openstack 同步依赖 2021-12-09 19:28:22 +08:00
Michael Bai
bbf2aff96c feat: 命令过滤器支持多维度绑定
feat: 修改命令过滤规则校验

feat: 修改系统用户命令过滤器迁移文件
2021-12-09 19:06:28 +08:00
ibuler
3ea4a9fbe6 chore: 修改 html 中 license 文案 2021-12-09 17:33:56 +08:00
fit2bot
3962af7c4f feat: 支持saml2协议的单点登录,合并代码 (#7347)
* fix: 支持saml2协议的单点登录

* feat: 支持saml2协议的单点登录,合并代码

Co-authored-by: jiangweidong <weidong.jiang@fit2cloud.com>
2021-12-09 15:47:21 +08:00
ibuler
38c6d11af1 perf: 修改关闭 issue 的 comment 2021-12-09 15:31:27 +08:00
fit2bot
5f45acf68f workflow: 修改 workflow (#7341)
* workflow: 修改 workflow

* fix: 修复判断的错误

* perf: 添加移除的内容

Co-authored-by: ibuler <ibuler@qq.com>
2021-12-09 12:07:55 +08:00
fit2bot
c7f2afc3c1 fix: redis lock bug (#7338)
Co-authored-by: feng626 <1304903146@qq.com>
2021-12-08 17:55:32 +08:00
xinwen
16fae00e0e feat: xrdp 远程应用 2021-12-08 15:55:49 +08:00
Eric_Lee
0afeed0ff1 feat: 录像增加 cast 格式 (#7259)
* feat: 录像增加 cast 格式

* perf: 优化一下写法

* perf: 修改一点点

Co-authored-by: ibuler <ibuler@qq.com>
2021-12-08 15:35:22 +08:00
Michael Bai
d72aa34513 fix: 修改命令过滤规则生成正则表达式的逻辑,提高命令过滤准确性 2021-12-08 10:24:33 +08:00
feng626
d56de16563 fix: 依赖bug 2021-12-07 19:01:14 +08:00
ibuler
8536e6fca7 perf: 添加 issues workflow 2021-12-07 18:29:53 +08:00
feng626
adb9f01231 feat: 密码计划邮件提醒 2021-12-07 17:00:33 +08:00
ibuler
e0d4ad8570 workflow: 优化workflow 2021-12-07 10:40:13 +08:00
ibuler
3c8726f1b0 fix: 去掉多余的 collect static
perf: 使用bash 才能保证 subprocess 运行正常
2021-12-06 19:03:23 +08:00
ibuler
6b4bc1bdb5 chore: 升级 License 到 GPLv3
chore: 升级 License 到 GPLv3
2021-12-06 18:15:17 +08:00
ibuler
c92d36391f chore: change license 2021-12-06 17:45:54 +08:00
xinwen
24bbe7c31f fix: 计算docker limit 内存使用率时区分 cgroup v1 v2 2021-12-06 11:22:45 +08:00
fit2bot
77f2bd9262 perf: 优化workflow名称 (#7323)
* workflow: 添加定时检查issue的workflow

* perf: 优化workflow名称

Co-authored-by: ibuler <ibuler@qq.com>
2021-12-06 10:09:58 +08:00
ibuler
495a6fbc95 workflow: 添加定时检查issue的workflow 2021-12-03 19:25:56 +08:00
xinwen
36c6299a03 fix: redis 锁在redis集群环境报错 2021-12-03 19:23:44 +08:00
ibuler
8a31fbe35e chore: 添加判断 pull request 2021-12-03 15:22:13 +08:00
ibuler
dbe628a8db chore: 添加 issue 备注添加labels 2021-12-03 15:22:13 +08:00
ibuler
e45b893662 chore: 添加 workflow 检查issue 2021-12-02 17:50:31 +08:00
feng626
ac4b6e5b96 feat: 工单创建资产添加节点 2021-11-30 16:38:30 +08:00
ibuler
c85249be36 perf: 优化订阅处理,形成框架 2021-11-29 15:01:37 +08:00
ibuler
de006bc664 perf: 资产添加标签显示,更加易读
pref: 添加翻译
2021-11-29 14:57:50 +08:00
xinwen
a313e011ef perf: 内存使用率兼顾 docker cgroup limit 2021-11-29 14:53:04 +08:00
Michael Bai
3076b7a5e1 fix: 修复migrations序号重复问题 2021-11-29 11:24:12 +08:00
老广
c47a588e7c Merge pull request #7289 from jumpserver/pr@dev@merge_with_master
Merge branch 'dev' of github.com:jumpserver/jumpserver into dev
2021-11-26 11:20:39 +08:00
ibuler
7f61c49db2 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev 2021-11-25 20:00:34 +08:00
ibuler
c8a76c9afb fix: 修复 close connection 的问题 2021-11-25 18:29:01 +08:00
ibuler
3e85a9a079 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev 2021-11-25 18:05:18 +08:00
ibuler
62cbca7eb2 fix: 修复重置 mfa 的提示问题 2021-11-25 17:50:47 +08:00
ibuler
434793bc41 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev 2021-11-25 17:44:51 +08:00
xinwen
85a017b2c4 fix: 按资产ip搜索数据不全 2021-11-25 17:29:47 +08:00
ibuler
84bce19a92 perf: 去掉登录页面更好 2021-11-25 16:02:40 +08:00
ibuler
3874b8ed67 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev
repr@dev_v2.16_v2.15@2ee26971c9b152@fix_xxxx
merges an updated upstream into a topic branch.
2021-11-25 15:58:33 +08:00
ibuler
7f0ad7e27f fix: 修复 oidc cas 登录时跳转问题
perf: 优化一波,容易debug

perf: 还原回来的世界
2021-11-25 15:01:42 +08:00
ibuler
2ee26971c9 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev 2021-11-24 20:41:41 +08:00
ibuler
5ace5a752e fix: 修复 cas/oidc 登录 MFA 产生的bug
perf: 优化更严谨
2021-11-24 19:05:15 +08:00
Michael Bai
e838d974c3 fix: 修复根据节点/资产查询授权时报错的问题 2021-11-24 19:04:42 +08:00
ibuler
9dd93ea3b8 Merge branch 'dev' of github.com:jumpserver/jumpserver into dev 2021-11-24 16:15:57 +08:00
jiangweidong
88ea7ae149 feat: 云管同步中心支持OpenStack资产同步,所需python库依赖 2021-11-24 14:28:11 +08:00
ibuler
1132c6a4e4 fix: 修复 mfa radius 登录的bug 2021-11-24 12:51:12 +08:00
ibuler
0762f87ba5 Merge branch 'master' into dev 2021-11-24 11:25:51 +08:00
chenqiao
cb98b4f80a feat:新增对sqlserver数据库托管 2021-11-24 11:21:04 +08:00
feng626
599d58e9f2 fix: 修复重置mfa 500 bug 2021-11-23 16:11:54 +08:00
ibuler
5c6f1730d5 perf: 系统用户密码不再trim空格 2021-11-23 10:41:58 +08:00
feng626
67d084fc43 perf: ip list 优化 2021-11-19 16:36:58 +08:00
feng626
24d0d52a0a perf: 优化ip黑白名单 2021-11-19 11:48:45 +08:00
xinwen
d94c515cfc fix: 验证码逻辑错误 2021-11-19 10:46:59 +08:00
Michael Bai
cae956f9a5 fix(i18n): 修改翻译文件 2021-11-18 19:07:14 +08:00
Jiangjie.Bai
2c70e117c6 Merge pull request #7229 from jumpserver/dev
v2.16
2021-11-18 18:51:57 +08:00
ibuler
70e8a03888 fix: 修复 mfa 登录时的 focus 错误 2021-11-18 18:49:22 +08:00
fit2bot
d2df8acd84 fix: 修复数据库连接没有关闭问题 (#7227)
* fix: 修复数据库连接没有关闭的bug

perf: websocket 断开也添加关闭数据库连接

* fix: 修复数据库连接没有关闭问题

Co-authored-by: ibuler <ibuler@qq.com>
2021-11-18 18:47:01 +08:00
Michael Bai
6e5dcc738e fix: 修改ldap分页日志为debug模式 2021-11-18 18:07:51 +08:00
Jiangjie.Bai
d1ccb4af15 Merge pull request #7224 from jumpserver/dev
v2.16.0 rc4
2021-11-18 17:05:35 +08:00
fit2bot
086ecfc046 perf: 优化全局ip限制逻辑 (#7220)
* perf: 优化全局ip限制逻辑

* perf: 优化全局ip限制逻辑 2

* perf: 优化全局ip限制逻辑 3

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-11-18 16:55:23 +08:00
Jiangjie.Bai
8f3765a98d Merge pull request #7217 from jumpserver/dev
v2.16.0 rc3
2021-11-18 13:02:51 +08:00
Michael Bai
2d6610b133 fix(settings): 修复LDAP系统设置中使用search_ou查询前执行strip操作 2021-11-18 13:01:20 +08:00
Jiangjie.Bai
5a82174c54 Merge pull request #7214 from jumpserver/dev
v2.16.0 rc2
2021-11-17 19:42:25 +08:00
Michael Bai
dac45f234a fix: 终端列表指标数值保留一位小数 2021-11-17 19:36:52 +08:00
Michael Bai
096b2cf8b8 fix: 修改翻译 2021-11-17 19:36:10 +08:00
fit2bot
0ed0f69be0 fix: 登录日志字段翻译 (#7211)
Co-authored-by: xinwen <coderWen@126.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2021-11-17 19:28:58 +08:00
fit2bot
8af88cd2c6 fix: 修复otp verify msg引起的500 (#7210)
Co-authored-by: ibuler <ibuler@qq.com>
2021-11-17 16:43:04 +08:00
feng626
2a9f0f8dcf perf: help信息迁移到public中 2021-11-17 15:44:50 +08:00
ibuler
cc2d47e6dc perf: 修复首页登录mfa错误提示 2021-11-16 11:33:40 +08:00
xinwen
22c9dfc0f2 fix: 系统用户 actions 2021-11-16 11:33:00 +08:00
fit2bot
ed01f2f1fb fix: 修复xrdp连接时报错 (#7202)
* fix: 修复xrdp连接时报错

perf: 添加注释

* perf: 去掉import

Co-authored-by: ibuler <ibuler@qq.com>
2021-11-16 11:32:25 +08:00
ibuler
c5ff0d972b perf: 去掉mfa input 的required,以为用户可能没有设置 2021-11-15 17:01:12 +08:00
ibuler
7d9da9ff66 perf: 修改名称 2021-11-15 17:01:12 +08:00
fit2bot
d6395b64fa merge: with dev (#7195)
* fix: 修复登录mfa时,选择了禁用的

* fix: mfa focus

Co-authored-by: ibuler <ibuler@qq.com>
2021-11-15 16:51:05 +08:00
xinwen
9bfbdea508 fix: 终端删除后,录像存储不能删除问题 2021-11-15 16:35:02 +08:00
ibuler
cb1c906db4 fix: 修复登录时没有绑定mfa,没有跳转的问题
fix: 首页登录如果没有则后续登录
2021-11-15 16:20:58 +08:00
ibuler
12a0096963 fix: 修复重置mfa的bug 2021-11-15 16:19:30 +08:00
ibuler
a315e8888b perf: 优化一下 win2016 不再内置 2021-11-15 16:18:31 +08:00
ibuler
454d3cba96 fix: 修复登录mfa时,选择了禁用的 2021-11-15 16:17:02 +08:00
feng626
4a786baf4e perf: 工单提示信息优化 2021-11-12 18:00:32 +08:00
xinwen
187977c04a fix: 修改 CPU info 字段 2021-11-12 17:09:42 +08:00
xinwen
4260fe1424 fix: 资产 cpu_info 翻译不对 2021-11-12 16:56:19 +08:00
Michael Bai
7286b1b09e fix: 移动【会话设置保留时间】至定期清理设置页面 2021-11-12 16:54:17 +08:00
xinwen
9a7919f3ac fix: 更新公钥消息不对 2021-11-12 16:44:23 +08:00
xinwen
43cbf4f6a9 fix: 创建存储时名称重复报错 2021-11-12 16:31:14 +08:00
Eric
e9dc1ad86a fix: 修复 ssh 工具连接无法二级登录的问题 2021-11-12 16:14:14 +08:00
feng626
90477146ed feat: 添加全局ip黑名单 2021-11-12 14:56:25 +08:00
ibuler
353b66bf8f fix: 修复创建token的问题 2021-11-11 19:10:28 +08:00
Jiangjie.Bai
3051996e35 Merge pull request #7169 from jumpserver/dev
v2.16.0 rc1
2021-11-11 14:00:33 +08:00
ibuler
8761ed741c pref: 资产的硬件信息可以更改 2021-11-11 13:31:18 +08:00
ibuler
0facd8a25e perf: 去掉官网的链接 2021-11-11 13:03:35 +08:00
xinwen
b28ce9de7a feat: xrdp session bpp 读取环境变量 2021-11-11 10:42:17 +08:00
jiangweidong
f2b72aae37 feat: 支持管理员配置导航栏上帮助中的url 2021-11-10 17:06:16 +08:00
ibuler
b001443f34 pref: 修改为内置 2021-11-10 16:59:08 +08:00
fit2bot
17303c0550 pref: 优化MFA (#7153)
* perf: 优化mfa 和登录

* perf: stash

* stash

* pref: 基本完成

* perf: remove init function

* perf: 优化命名

* perf: 优化backends

* perf: 基本完成优化

* perf: 修复首页登录时没有 toastr 的问题

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2021-11-10 11:30:48 +08:00
xinwen
bac974b4f2 feat: 异地登录提醒可配置是否启用 2021-11-09 14:35:54 +08:00
Michael Bai
f9e970f4ed fix: 修改文案 切换用户 -> 用户切换 2021-11-05 16:41:45 +08:00
Jiangjie.Bai
07c60ca75d feat: 支持二级登录资产 (#7143)
* feat: 支持su切换系统用户

* feat: 支持su切换系统用户

* feat: 支持su切换系统用户
2021-11-05 16:11:29 +08:00
ibuler
bbe2678df3 perf: 优化用户创建邮件信息,支持部分标签 2021-11-04 13:45:15 +08:00
ibuler
d57f52ee24 feat: 添加 window RDP TLS 平台 2021-11-04 11:05:50 +08:00
feng626
55775f0deb perf: 异地登陆去掉本地判断 2021-11-02 21:11:17 +08:00
xinwen
fde118021e fix: Radius 配置 2021-11-02 20:13:14 +08:00
ibuler
d484885762 perf: 修复ansible stdout 中非utf8的问题 2021-11-02 20:12:48 +08:00
feng626
8071f45f92 fix: 修复xpack引入包问题 2021-10-29 16:23:49 +08:00
Jiangjie.Bai
15cdd44c6c Merge pull request #7107 from jumpserver/dev
v2.15.0
2021-10-28 17:45:42 +08:00
feng626
d44f90ea3d fix: acl xpack 2021-10-28 17:38:55 +08:00
Jiangjie.Bai
42e9fbf37a Merge pull request #7103 from jumpserver/dev
v2.15.0
2021-10-28 15:31:44 +08:00
ibuler
d44656aa10 fix: 修复修改用户信息后,绑定丢失
perf: 还原提示文案
2021-10-28 15:29:55 +08:00
feng626
09d4228182 Merge pull request #7102 from jumpserver/pr@dev@ticket_tips
perf: 工单错误提示优化
2021-10-28 15:25:42 +08:00
feng626
3ae8da231a perf: 工单错误提示优化 2021-10-28 15:16:52 +08:00
feng626
2e4b6d150a fix: 登录复合浏览器不兼容 2021-10-28 15:02:54 +08:00
Michael Bai
8542d53aff fix: 修复ldap用户导入时字段进行strip 2021-10-28 15:02:33 +08:00
Michael Bai
141dafc8bf fix: 创建授权/添加资产到节点;不再自动更新资产的管理用户 2021-10-28 13:39:27 +08:00
Michael Bai
28a6024b49 fix: 修改工单列表默认按照创建日志倒叙排序,修改翻译 2021-10-28 13:38:10 +08:00
ibuler
6cf2bc4baf pref: 优化工单验证 2021-10-28 13:37:24 +08:00
xinwen
631f802961 fix: 钉钉报错的时取得字段不对 2021-10-28 13:31:27 +08:00
feng626
0eedda748a perf: acl username unified 2021-10-28 13:31:05 +08:00
Jiangjie.Bai
7183f0d274 Merge pull request #7089 from jumpserver/dev
v2.15.0-rc3
2021-10-27 19:24:42 +08:00
feng626
c93ab15351 fix: acl migrate bug 2021-10-27 11:31:16 +08:00
Michael Bai
3fffd667dc fix: 修改系统用户、工单列表排序字段 2021-10-27 11:16:01 +08:00
fit2bot
11fd2afa3a perf: 优化下载页面 (#7082)
Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2021-10-26 17:27:01 +08:00
Michael Bai
1eb59b11da fix: 添加Model的verbose_name属性 2021-10-26 17:22:05 +08:00
feng626
a1e2d4ca57 Merge pull request #7081 from jumpserver/pr@dev@command_record_filter
fix: 命令记录-导出选择项命令:却导出了所有命令
2021-10-26 16:54:27 +08:00
feng626
8a413563be fix: 命令记录-导出选择项命令:却导出了所有命令 2021-10-26 16:50:14 +08:00
ibuler
203a01240b perf: 优化dockerfile 2021-10-26 15:48:17 +08:00
Michael Bai
37fef6153a fix: 修改依赖包版本: jumpserver-django-oidc-rp==0.3.7.8 2021-10-26 15:16:24 +08:00
feng626
ba6c49e62b Merge pull request #7077 from jumpserver/pr@dev@app_account_translate
fix: 【【账号管理】应用账号导出字段存在英文】
2021-10-26 13:42:31 +08:00
feng626
da79f8beab fix: 【【账号管理】应用账号导出字段存在英文】 2021-10-26 13:34:59 +08:00
ibuler
3f72c02049 perf: 添加命令org 2021-10-26 11:49:56 +08:00
feng626
380226a7d2 fix: 用户登陆mfa code为空限制 2021-10-26 11:01:12 +08:00
fit2bot
f88e5de3c1 perf: 优化用户创建邮件 (#7072)
* perf: 优化通知中的连接点击

* perf: 优化用户创建邮件

* perf: 优化时间日期

Co-authored-by: ibuler <ibuler@qq.com>
2021-10-26 10:52:23 +08:00
Michael Bai
7c149fe91b fix: 修复系统用户applications_amount字段只读 2021-10-25 16:25:12 +08:00
Jiangjie.Bai
f673fed706 Merge pull request #7068 from jumpserver/dev
v2.15.0-rc2
2021-10-25 15:07:25 +08:00
Michael Bai
84326cc999 fix: 系统用户列表添加 应用数量 字段 2021-10-25 15:01:29 +08:00
xinwen
7d56678a8e fix: 修复登录次数出现 0 2021-10-25 14:30:48 +08:00
feng626
25d1b71448 fix: 修复分时登陆bug 2021-10-25 14:26:47 +08:00
feng626
d3920a0cc9 Merge pull request #7065 from jumpserver/pr@dev@ticket_bug
fix: 修复工单发邮件及授权资产备注信息修改
2021-10-25 11:32:01 +08:00
feng626
52889cb67a fix: 修复工单发邮件及授权资产备注信息修改 2021-10-25 11:30:37 +08:00
feng626
0b67c7a953 fix: 修复登陆复合acl时 未添加规则bug 2021-10-25 10:49:00 +08:00
ibuler
1f50a2fe33 perf: 优化签名 2021-10-25 10:48:27 +08:00
ibuler
cd5094f10d perf: 优化通知中的连接点击 2021-10-25 10:48:03 +08:00
fit2bot
c244cf5f43 pref: 修改使用的消息内容 (#7061)
* perf:  再次优化通知

* pref: 修改使用的消息内容

* perf: 修复url地址

Co-authored-by: ibuler <ibuler@qq.com>
2021-10-22 20:06:16 +08:00
feng626
a0db2f6ef8 Merge pull request #7059 from jumpserver/pr@dev@ticket_send_message_multiple_times
fix: 修复工单结束重复发送受理人消息bug
2021-10-22 16:40:51 +08:00
feng626
ea485c3070 fix: 修复工单结束重复发送受理人消息bug 2021-10-22 16:38:14 +08:00
feng626
705f352cb9 Merge pull request #7057 from jumpserver/pr@dev@acl_bug
fix: 修复acl 选择时间段为空bug
2021-10-22 16:12:40 +08:00
feng626
dc13134b7b fix: 修复acl 选择时间段为空bug 2021-10-22 16:09:22 +08:00
Michael Bai
06de6c3575 fix: 修复资产系统用户auth-info获取流程及创建时手动登录方式的校验 2021-10-22 15:19:58 +08:00
ibuler
c341d01e5a perf: 修改工单信息 2021-10-21 20:04:27 +08:00
feng626
d1a3d31d3f feat: 客户端协议内容添加rdp文件名 2021-10-21 19:16:04 +08:00
ibuler
10f4ff4eec fix: 修复工单通知内容bug 2021-10-21 18:36:29 +08:00
ibuler
25ea3ba01d perf: 修改sdk位置 2021-10-21 17:39:28 +08:00
ibuler
072865f3e5 perf: 优化修改 sdk 位置 2021-10-21 17:39:28 +08:00
ibuler
d5c9ec1c3d perf: 优化位置 2021-10-21 17:39:28 +08:00
ibuler
487c945d1d perf: 修改代码位置,用户sugestion增加到6个 2021-10-21 17:39:28 +08:00
feng626
a78b2f4b62 fix: 修复工单发消息报错 2021-10-21 17:31:59 +08:00
ibuler
a1f1dce56b perf: 修改格式错误 2021-10-21 16:22:08 +08:00
xinwen
a1221a39fd fix: 会话管理翻译 2021-10-21 16:21:49 +08:00
xinwen
8c118b6f47 fix: 组织删除报错未翻译 2021-10-21 16:21:11 +08:00
feng626
68fd8012d8 Merge pull request #7042 from jumpserver/pr@dev@acl_perf
perf: acl filter
2021-10-21 15:11:50 +08:00
feng626
526928518d perf: acl filter 2021-10-21 15:00:29 +08:00
feng626
c5f6c564a7 fix: 系统启动bug 2021-10-21 13:05:07 +08:00
Jiangjie.Bai
076adec218 Merge pull request #7033 from jumpserver/dev
v2.15.0 rc1
2021-10-20 20:24:29 +08:00
fit2bot
00d434ceea perf: 优化消息通知 (#7024)
* perf: 优化系统用户列表

* stash

* perf: 优化消息通知

* perf: 修改钉钉

* perf: 修改优化消息通知

* perf: 修改requirements

* perf: 优化datetime

Co-authored-by: ibuler <ibuler@qq.com>
2021-10-20 19:45:37 +08:00
fit2bot
9acfd461b4 feat: user login acl (#6963)
* feat: user login acl

* 添加分时登陆

* acl 部分还原

* 简化acl判断逻辑

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2021-10-20 17:56:59 +08:00
feng626
9424929dde fix: sms bug 2021-10-19 20:23:06 +08:00
Michael Bai
b95d3ac9be fix: 修改终端status翻译 2021-10-19 16:16:48 +08:00
Michael Bai
af2a9bb1e6 fix: 修复用户登录失败未记录日志的问题 2021-10-19 15:28:39 +08:00
fit2bot
63638ed1ce feat: 首页的 chanlege 和 MFA 统一 (#6989)
* feat: 首页的 chanlege 和 MFA 统一

* 登陆样式调整

* mfa bug

* q

* m

* mfa封装组件 前端可修改配置

* perf: 添加翻译

* login css bug

* perf: 修改一些风格

* perf: 修改命名

* perf: 修改 mfa code 不是必填

* mfa 前端统一组件

* stash

* perf: 统一验证码

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
2021-10-18 18:41:41 +08:00
fit2bot
fa68389028 perf: 去掉单独的flash msg (#7013)
* perf: 去掉单独的flash msg

perf: 修改使用库

* fix: guangbug

* pref: 修改 context

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: xinwen <coderWen@126.com>
2021-10-18 11:25:39 +08:00
halo
63b338085a feat: 修改username校验,telnet协议支持输入中文 2021-10-15 15:36:29 +08:00
fit2bot
5d8818e69e feat: 添加资产授权用户API、资产授权用户的授权规则API (#7008)
* feat: 添加资产授权用户API、资产授权用户的授权规则API

* feat: 添加资产授权用户组API、资产授权用户组的授权规则API

* feat: 抽象API类

Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-10-15 14:02:32 +08:00
xinwen
77521119b9 fix: 修改 oauth 认证提示信息 2021-10-15 11:32:20 +08:00
ibuler
baee71e4b8 perf: 添加requirements 2021-10-15 11:31:06 +08:00
ibuler
6459c20516 perf: Django语言文件推送到lfs
perf: 修改mac依赖,添加安装 git lfs

perf: 修改添加 mac 开发环境依赖
2021-10-14 16:30:18 +08:00
ibuler
0207fe60c5 perf: 修改ip城市获取算法
perf: 优化使用lfs
2021-10-14 10:35:18 +08:00
Eric
b8c43f5944 fix: 修复获取系统用户密码问题 2021-10-13 14:34:57 +08:00
xinwen
63ca2ab182 fix: 修复 traceback 问题 2021-10-13 11:42:54 +08:00
ibuler
f9ea119928 perf: 不再需要 tls 类型,any 方式都可以 2021-10-12 17:45:38 +08:00
xinwen.xu
d4bdc74bd8 feat: 授权过期通知 2021-10-11 15:41:13 +08:00
ibuler
42e7ca6a18 perf: 资产编号允许api更改 2021-10-11 15:26:31 +08:00
xinwen
6e0341b7b1 feat: xrdp挂载受授权的上传下载控制 2021-10-11 15:24:34 +08:00
jiangweidong
2f25e2b24c fix: 系统用户认证方式从托管密码更新到手动输入模式后,不填写用户名报错 2021-10-11 10:02:48 +08:00
halo
87dcd2dcb7 feat: 增加关闭第三方登录跳转配置参数 2021-09-29 16:04:59 +08:00
ibuler
e96aac058f fix: 修复跳转msg页面,取消button太小的问题 2021-09-29 15:30:17 +08:00
Jiangjie.Bai
d76bad125b Merge pull request #6973 from jumpserver/pr@dev@feat_announcement
feat: 支持公告
2021-09-29 14:58:15 +08:00
ibuler
913b1a1426 perf: 修改翻译 2021-09-29 14:55:14 +08:00
ibuler
0213154a19 merge: with dev 2021-09-29 14:53:42 +08:00
ibuler
8f63b488b2 perf: 修改翻译 2021-09-29 14:43:00 +08:00
ibuler
f8921004c2 perf: 修改依赖版本 2021-09-29 14:42:11 +08:00
feng626
5588eab57e feat: 用户异地登陆 2021-09-29 14:33:52 +08:00
ibuler
e0a8f91741 perf: 修改翻译 2021-09-28 18:57:21 +08:00
ibuler
467ebfa650 perf: 添加公告id 2021-09-28 18:17:10 +08:00
ibuler
0533b77b1b perf: 支持公告 2021-09-28 17:01:47 +08:00
ibuler
a558ee2ac0 perf: 修改dockerfile 2021-09-28 10:10:20 +08:00
ibuler
46a39701d4 fix: 修复docker无法构建 2021-09-27 19:27:33 +08:00
ibuler
8c3ab31e4e fix: 修复由于修改filter引起的问题 2021-09-27 18:50:29 +08:00
Jiangjie.Bai
476e6cdc2f Merge pull request #6932 from jumpserver/pr@dev@perf_remove_djangopo
perf: 去掉django.po
2021-09-27 14:12:26 +08:00
ibuler
0b593f4555 perf: 优化drf filter, 修改terminal filter
perf: 去掉debug

perf: 去掉debug
2021-09-27 14:09:22 +08:00
ibuler
456116938d perf: 优化数据迁移,性能提升50倍 2021-09-27 14:05:21 +08:00
ibuler
76b24f62d4 perf: merge with dev 2021-09-27 14:03:19 +08:00
Michael Bai
e1eef0a3f3 fix: 修复authbook systemuser字段问题 2021-09-24 20:24:25 +08:00
Michael Bai
2c74727b65 fix: 修复邮件测试序列类及API 2021-09-24 14:13:55 +08:00
ibuler
08cd91c426 perf: 修改应用授权树,没有的时候不显示 2021-09-24 14:12:31 +08:00
wojiushixiaobai
90d269d2a2 fix: 添加包 2021-09-24 12:56:35 +08:00
Michael Bai
a9ddbcc0cd fix: 修复系统用户和资产/节点关联时资产特权用户更新的问题 2021-09-24 12:48:35 +08:00
Michael Bai
aec31128cf perf: 修改翻译 2021-09-23 11:14:53 +08:00
ibuler
b415ee051d perf: 去掉django.po 2021-09-23 10:26:39 +08:00
ibuler
082a5ae84c perf: 修改不再添加编译后的翻译文件 2021-09-22 18:53:04 +08:00
老广
6b7554d69a Merge pull request #6929 from jumpserver/pr@dev@ticket_comment
perf: 工单优化
2021-09-22 15:51:10 +08:00
feng626
5923562440 perf: 工单优化 2021-09-22 15:17:57 +08:00
老广
d144e7e572 Merge pull request #6922 from jumpserver/pr@dev@fix_tokensmsoptions
fix: 修复KoKo登录时,未开启SMS服务出现了SMS选项的问题
2021-09-22 11:24:03 +08:00
ibuler
cafbd08986 perf: 修改啊 2021-09-22 11:18:38 +08:00
ibuler
b436fc9b44 perf: 优化登录 2021-09-22 11:18:38 +08:00
ibuler
26fc56b4be perf: 优化登录html 2021-09-22 11:18:38 +08:00
Michael Bai
3b1d199669 fix: 修复KoKo登录时,未开启SMS服务出现了SMS选项的问题 2021-09-22 03:17:14 +00:00
ibuler
e7edbc9d84 perf: 修改啊 2021-09-18 15:46:41 +08:00
ibuler
41f81bc0bf merge: with dev 2021-09-18 15:29:29 +08:00
ibuler
75d2c81d33 perf: 优化登录 2021-09-18 15:24:04 +08:00
ibuler
da2dea5003 perf: 登录错误提示颜色 2021-09-18 15:07:05 +08:00
老广
fc60156c23 Merge pull request #6913 from jumpserver/pr@dev@perf_dockerfile
perf: 优化依赖包
2021-09-17 18:03:31 +08:00
wojiushixiaobai
76fb547551 perf: 优化依赖包 2021-09-17 16:14:15 +08:00
ibuler
e686f51703 perf: 优化登录html 2021-09-17 16:00:23 +08:00
feng626
7578bda588 Merge pull request #6911 from jumpserver/pr@dev@ticket_perf
perf: 工单优化
2021-09-17 15:50:48 +08:00
feng626
f2d743ec2b perf: 工单优化 2021-09-17 15:46:33 +08:00
ibuler
7099aef360 perf: 登录错误提示颜色 2021-09-17 14:35:05 +08:00
wojiushixiaobai
246f5d8a11 fix: 添加依赖 2021-09-16 23:24:02 +08:00
wojiushixiaobai
6c98bd3b48 fix: 添加 pg 依赖包 2021-09-16 23:24:02 +08:00
老广
6def113cbd Merge pull request #6902 from jumpserver/dev
v2.14.0
2021-09-16 21:17:25 +08:00
ibuler
2dc0af2553 perf: 优化 dockerfile 2021-09-16 21:08:04 +08:00
Jiangjie.Bai
a291592e59 Merge pull request #6900 from jumpserver/dev
修改依赖包版本 jumpserver-django-oidc-rp==0.3.7.7
2021-09-16 20:15:32 +08:00
Michael Bai
6fb4c1e181 修改依赖包版本 jumpserver-django-oidc-rp==0.3.7.7 2021-09-16 19:49:42 +08:00
老广
eee093742c Merge pull request #6898 from jumpserver/dev
merge: dev to master
2021-09-16 19:35:39 +08:00
feng626
743c9bc3f1 fix: 过滤其它类型app 2021-09-16 19:30:32 +08:00
ibuler
f963c5ef9d perf: 修改翻译 2021-09-16 19:29:05 +08:00
ibuler
2c46072db2 fix: 修复serializer问题 2021-09-16 19:08:21 +08:00
xinwen
b375cd3e75 fix: otp 绑定问题 2021-09-16 19:04:19 +08:00
fit2bot
c26ca20ad8 fix: 更新OIDC配置时,将keycloak配置转换为openid (#6893)
* fix: 修改磁盘使用等key值

* fix: 更新OIDC配置时,将keycloak配置转换为openid

Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-16 18:57:09 +08:00
Jiangjie.Bai
982a510213 Merge pull request #6892 from jumpserver/ibuler-patch-1
Update README.md
2021-09-16 17:46:06 +08:00
老广
5d6880f6e9 Update README.md 2021-09-16 17:45:10 +08:00
xinwen
a784a33203 fix: 去掉手动系统用户提示输入密码 2021-09-16 16:47:15 +08:00
xinwen
a452f3307f fix: 组件监控的消息 2021-09-16 16:29:56 +08:00
Michael Bai
b7a6287925 fix: 修改磁盘使用等key值 2021-09-16 16:29:19 +08:00
feng626
3cba8648cb fix: 工单日期bug 2021-09-16 16:12:42 +08:00
ibuler
ef7b2b7980 perf: 优化登录错误提示 2021-09-16 14:07:51 +08:00
xinwen
1ab247ac22 fix: 用户密码过期提醒 2021-09-16 13:43:09 +08:00
Michael Bai
ef8a027849 fix: 修改翻译,链接过期 2021-09-16 11:16:21 +08:00
Michael Bai
7890e43f5a fix: 修改网关测试可连接性报错提示信息 2021-09-16 11:00:10 +08:00
fit2bot
2030cbd19d fix: 修复authbook信号监听;添加翻译文件.mo (#6882)
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2021-09-16 10:36:24 +08:00
feng626
0f7c8c2570 fix: 工单复核bug 2021-09-16 10:35:19 +08:00
Jiangjie.Bai
9b60d86ddd Merge pull request #6880 from jumpserver/dev
v2.14.0 rc3
2021-09-15 21:05:26 +08:00
ibuler
f129f99faa perf: 优化修改获取Hostname 2021-09-15 21:04:56 +08:00
fit2bot
43f30b37da fix: 用户手机号没有校验 (#6875)
Co-authored-by: xinwen <coderWen@126.com>
Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
2021-09-15 21:00:54 +08:00
xinwen
45aefa6b75 fix: 修改一些翻译 2021-09-15 20:59:50 +08:00
xinwen
b30123054b fix: xrdp 手动登录系统用户仍然不需要输入密码 2021-09-15 20:58:56 +08:00
wojiushixiaobai
b456e71ec4 perf: 更新 client 链接 2021-09-15 20:57:04 +08:00
xinwen
7560b70c4d feat: 用户详情页面显示 手机号,钉钉,企业微信,飞书 2021-09-15 19:42:24 +08:00
Michael Bai
0c96df5283 fix: 系统用户序列类返回nodes 2021-09-15 19:41:45 +08:00
fit2bot
9dda19b8d7 fix: 修改LDAP同步提示信息 (#6872)
* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

* fix: 修改LDAP同步提示信息

Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-15 19:16:44 +08:00
fit2bot
fbe5f9a63a fix: 修改资产和特权用户发生变化时,更新资产的admin_user (#6871)
* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

* fix: 修改资产和特权用户发生变化时,更新资产的admin_user

Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-15 19:11:19 +08:00
xinwen
1c4b4951dc fix: 一些提示 2021-09-15 18:06:57 +08:00
ibuler
8e12399058 perf: 资产序列类优化,改为只读 2021-09-15 18:05:55 +08:00
ibuler
741b96ddee perf: 优化设置中的数字大小 2021-09-15 17:22:23 +08:00
xinwen
8c3f89ee51 fix: 高危命令告警偶发 session 不存在 2021-09-15 17:21:36 +08:00
xinwen
dee45ce2e0 fix: 用户离开组织命令复核没有删除 2021-09-15 17:19:37 +08:00
ibuler
cfab30f7f7 perf: 修改 i18n 2021-09-15 17:18:17 +08:00
Michael Bai
02e9a96792 fix: 修改翻译 2021-09-15 17:09:48 +08:00
feng626
aa6dcdc65d Merge pull request #6862 from jumpserver/pr@dev@ticket_time_validation
fix: 工单失效日期小于开始日期
2021-09-15 16:44:23 +08:00
feng626
5a6b64eebd fix: 工单失效日期小于开始日期 2021-09-15 16:25:43 +08:00
feng626
2dd7867b32 Merge pull request #6860 from jumpserver/pr@dev@login_confirm
fix: 登陆复核返回后 删除工单
2021-09-15 15:42:18 +08:00
feng626
6507f0982c fix: 登陆复核返回后 删除工单 2021-09-15 15:39:34 +08:00
ibuler
c115ef7b47 perf: 优化ttl 2021-09-15 15:27:04 +08:00
xinwen
bf68ddf09e fix: 腾讯短信检测是否发送成功 2021-09-15 15:26:35 +08:00
xinwen
f3906ff998 fix: 用户导出 can_public_key_auth 没翻译 2021-09-15 15:25:52 +08:00
Michael Bai
e47ee43631 fix: 修改默认es doc_type 为 _doc 2021-09-15 15:25:09 +08:00
xinwen
d22bb2c92f fix: 重置密码连接生成多个token 2021-09-15 11:58:26 +08:00
xinwen
870dac37b9 fix: 重置密码成功的消息里有 br 标签 2021-09-15 11:10:57 +08:00
feng626
d14c5c58ff Merge pull request #6855 from jumpserver/pr@dev@ticket_notice_bug
fix: ticket_notice_bug
2021-09-14 22:33:42 +08:00
feng626
a6b40510d0 fix: ticket_notice_bug 2021-09-14 22:32:13 +08:00
feng626
f762fe73ff fix: 工单拒绝清除mfa 2021-09-14 19:36:03 +08:00
xinwen
d49d1ba055 perf: oauth2 登录不再限制只能本地用户 2021-09-14 17:40:51 +08:00
ibuler
6e3d950e23 perf: 优化迁移账号,性能提高50倍 2021-09-14 17:39:27 +08:00
Michael Bai
7939ef34b0 fix: 修复服务告警主题替换<br> 2021-09-14 17:39:06 +08:00
Michael Bai
07cd930c0e fix: 删除配置 PERIOD_TASK_ENABLED 2021-09-14 17:38:47 +08:00
Michael Bai
c14c89a758 fix: 修改CAS配置项和CAS登录失败问题 2021-09-14 16:43:57 +08:00
feng626
245367ec29 Merge pull request #6844 from jumpserver/pr@dev@ticket_bug
fix: 修复工单消息推送bug
2021-09-14 15:56:35 +08:00
feng626
c5f4ecc8cc fix: 修复工单消息推送bug 2021-09-14 15:48:22 +08:00
ibuler
eb8bdf8623 perf: 添加安全说明 2021-09-14 14:47:40 +08:00
Michael Bai
a26c5a5e32 fix: 修复设置未分组节点显示单独授权资产的配置时,用户授权树没有变化的问题 2021-09-14 14:46:51 +08:00
Michael Bai
068db6d1ca fix: 修复设置未分组节点显示单独授权资产的配置时,用户授权树没有变化的问题 2021-09-14 14:46:51 +08:00
Michael Bai
e6e2a35745 fix: 修复设置未分组节点显示单独授权资产的配置时,用户授权树没有变化的问题 2021-09-14 14:46:51 +08:00
feng626
fafc2791ab Merge pull request #6841 from jumpserver/pr@dev@ticket_bug
fix: 工单不同组织取相应资产的名字
2021-09-14 14:10:09 +08:00
feng626
39507ef152 fix: 工单不同组织取相应资产的名字 2021-09-14 14:03:28 +08:00
Jiangjie.Bai
683fb9f596 Merge pull request #6838 from jumpserver/dev
v2.14.0 rc2
2021-09-14 00:05:35 +08:00
Bai
ced9e53d62 fix: 修复 debug 日志信息 2021-09-14 00:04:17 +08:00
Jiangjie.Bai
93846234f8 Merge pull request #6834 from jumpserver/dev
v2.14.0 rc2
2021-09-13 21:27:15 +08:00
ibuler
8ac7d4b682 perf: 优化登录backends 2021-09-13 21:26:45 +08:00
Michael Bai
c4890f66e1 fix: i18n 2021-09-13 20:45:34 +08:00
Michael Bai
4618989813 fix: i18n 2021-09-13 20:39:18 +08:00
xinwen
29645768a0 fix: 登录复核没有日志 2021-09-13 20:39:18 +08:00
Michael Bai
8f1c934f73 fix: 授权规则支持通过 from_ticket 工单过滤 2021-09-13 20:24:27 +08:00
fit2bot
7a45f4d129 perf: 优化短信 (#6826)
* perf: 优化短信

* refactor: 适配新的短信模板配置

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: xinwen <coderWen@126.com>
2021-09-13 20:15:59 +08:00
feng626
55a5dd1e34 fix: ticket bug 2021-09-13 20:12:34 +08:00
xinwen
6695d0a8a2 fix: 用户不能禁用或启用自己 2021-09-13 19:52:30 +08:00
Michael Bai
84d6b3de26 fix: 修改测试网关端口错误时提示信息 2021-09-13 19:06:25 +08:00
feng626
17a5e919d5 fix: ticket bug 2021-09-13 19:05:41 +08:00
feng626
3ba07867c8 Merge pull request #6824 from jumpserver/pr@dev@fix_system_msg
feat: 工单多种审批
2021-09-13 18:59:03 +08:00
feng626
75b76170f9 feat: 工单多种审批 2021-09-13 18:54:02 +08:00
xinwen
d34c7edb00 refactor: 重构消息 2021-09-13 18:52:02 +08:00
feng626
f64740c2db fix: 修改翻译及建议接口 2021-09-13 18:04:01 +08:00
Michael Bai
3a09845c29 fix: 修复终端启动时更新remote_addr字段 2021-09-13 18:03:06 +08:00
xinwen
09d51fd5be fix: OTP_IN_RADIUS 与 mfa 冲突 2021-09-13 17:43:19 +08:00
Michael Bai
fc8181b5ed fix: 修复删除关联了资产的特权用户失败的问题 2021-09-13 17:33:27 +08:00
feng626
5a993c255d Merge pull request #6818 from jumpserver/pr@dev@fix_ticket_bug
fix: 修复工单与koko相关接口bug
2021-09-13 16:26:45 +08:00
feng626
ad592fa504 fix: 修复工单与koko相关接口bug 2021-09-13 16:23:58 +08:00
feng626
1dcc8ff0a3 Merge pull request #6816 from jumpserver/pr@dev@perm_user_node_tree_bug
fix: 修复用户详情获取子节点bug
2021-09-13 15:30:49 +08:00
feng626
11a9a49bf8 fix: 修复用户详情获取子节点bug 2021-09-13 15:23:12 +08:00
Michael Bai
b9ffc23066 fix: 修复应用账号不能通过用户名过滤的问题 2021-09-13 15:09:13 +08:00
feng626
ea4dccbab8 fix: 修复工单bug 2021-09-13 14:12:33 +08:00
Michael Bai
683461a49b 修改 FORGOT_PASSWORD_URL 允许为空 2021-09-13 14:02:46 +08:00
Michael Bai
1a1ad0f1a2 perf: 取消API Token的配置 2021-09-13 14:02:46 +08:00
xinwen
773f7048be fix: 通知暂不支持短信 2021-09-13 13:30:54 +08:00
xinwen
f8f783745c fix: 修改密码没有发通知 2021-09-13 13:30:54 +08:00
xinwen
4fe715d953 fix: 首次登录不能提交 2021-09-13 13:29:07 +08:00
Michael Bai
36dfc4bcb8 fix: i18n 2021-09-10 19:02:38 +08:00
xinwen
8925314dc7 refactor: 修改多对多关系日志样式 2021-09-10 19:02:38 +08:00
ibuler
817c02c667 fix: 修复is_app bug 2021-09-10 18:02:07 +08:00
xinwen
58a10778cd fix: 修复短信问题 2021-09-10 18:01:36 +08:00
Michael Bai
fa81652de5 perf: 修改授权中(资产/应用)系统用户字段不必填 2021-09-10 17:55:08 +08:00
fit2bot
7e6fa27719 perf: 优化通知 (#6798)
* perf: 优化通知

* perf: 优化危险命令提示

* fix: i18n

* fix: i18n

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-10 17:54:34 +08:00
xinwen
3e737c8cb8 fix: 修复短信问题 2021-09-10 16:43:52 +08:00
feng626
345c0fcf4f fix: 修复工单流bug 添加登陆审核配置 2021-09-10 16:22:30 +08:00
Michael Bai
bf6b685e8c fix: api/health/健康检测添加localhost 2021-09-10 15:11:25 +08:00
xinwen
654ec4970e 更改设置接口 2021-09-10 13:52:51 +08:00
feng626
4a436856b4 feat: sms setting 2021-09-10 13:52:51 +08:00
Jiangjie.Bai
e993e7257c Merge pull request #6795 from jumpserver/dev
v2.14.0 rc1
2021-09-09 21:18:32 +08:00
Michael Bai
f12a59da2f fix: 修改翻译 2021-09-09 21:14:44 +08:00
Michael Bai
42c3c85863 fix: 修改翻译 2021-09-09 21:14:44 +08:00
xinwen
7e638ff8de fix: 翻译 2021-09-09 20:49:56 +08:00
Michael Bai
932a65b840 perf: 修复批量更新组织失败的问题 2021-09-09 20:49:30 +08:00
fit2bot
81000953e2 fix: 修改消息订阅 (#6789)
Co-authored-by: xinwen <coderWen@126.com>
2021-09-09 20:12:52 +08:00
fit2bot
dc742d1281 perf: 提交禁用xrdp的开关 (#6788)
* perf: 提交禁用xrdp的开关

* perf: 修复换行

Co-authored-by: ibuler <ibuler@qq.com>
2021-09-09 19:18:37 +08:00
xinwen
b1fceca8a6 feat: 添加短信服务和用户消息通知 2021-09-09 16:47:24 +08:00
ibuler
d49d1e1414 perf: 修改添加downlaod 2021-09-09 16:31:32 +08:00
xinwen
dac3f7fc71 refactor: 修改 xrdp 挂载磁盘参数名称 2021-09-09 16:31:03 +08:00
Jiangjie.Bai
47989c41a3 perf: Update README 2021-09-09 16:17:46 +08:00
Michael Bai
ca34216141 perf: 优化Core/Celery注册终端名称 2021-09-09 16:17:23 +08:00
fit2cloud-jiangweidong
905014d441 feat: 改密计划支持数据库改密 (#6709)
* feat: 改密计划支持数据库改密

* fix: 将数据库账户信息不保存在资产信息里,保存到自己的存储中

* perf: 早餐村

* perf: 修改account

* perf: 修改app和系统用户

* perf: 优化系统用户和应用关系

* fix: 修复oracle不可连接问题

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-09 16:04:54 +08:00
feng626
3e51f4d616 fix: 修复授权500 2021-09-09 14:43:03 +08:00
fit2bot
07179a4d22 feat: 页面配置serializer版 (#6750)
* feat: 页面配置serializer版

* perf: 优化配置

* perf: 优化设置

* perf: 优化设置

* perf: 优化配置页面

* perf: 基本完成设置优化

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
2021-09-09 14:00:50 +08:00
Michael Bai
7a2e93c087 perf: 优化终端注册时名称长度处理逻辑 2021-09-09 13:27:27 +08:00
xinwen
3fb368c741 fix: 修复 xrdp domain 不生效 2021-09-08 17:54:03 +08:00
fit2bot
fca3a8fbca perf: 绑定MFA认证密码时对密码进行加密传输 (#6776)
* perf: 绑定MFA认证密码时对密码进行加密传输

* perf: 绑定MFA认证密码时对密码进行加密传输

Co-authored-by: Michael Bai <baijiangjie@gmail.com>
2021-09-08 16:40:09 +08:00
xinwen
c1375ed7cb feat: xrdp 支持挂载本地磁盘(仅适用于 win) 2021-09-07 19:10:27 +08:00
Michael Bai
8b483b8c36 fix: 终端获取配置API返回SECURITY_SESSION_SHARE 2021-09-07 19:07:50 +08:00
Jiangjie.Bai
c465fccc33 feat: 支持 Session 会话共享 (#6768)
* feat: 添加 SECURITY_SESSION_SHARE 配置

* feat: 添加 SessionShare / ShareJoinRecord Model

* feat: 添加 SessionShare / ShareJoinRecord Model

* feat: 添加 SessionSharing / SessionJoinRecord Model

* feat: 添加 SessionSharing API

* feat: 添加 SessionJoinRecord API

* feat: 修改迁移文件

* feat: 修改迁移文件

* feat: 修改迁移文件

* feat: 修改API权限
2021-09-07 18:16:27 +08:00
ibuler
3d934dc7c0 perf: 优化迁移 2021-09-06 19:57:37 +08:00
feng626
b69ed8cbe9 Merge pull request #6767 from jumpserver/pr@dev@keep_only_flow_app_asset
perf: 只保留app asset flow
2021-09-06 18:45:50 +08:00
feng626
c27230762b perf: 只保留app asset flow 2021-09-06 18:44:58 +08:00
Bai
7ea8205672 feat: 云管中心添加GCP 2021-09-06 18:21:15 +08:00
wojiushixiaobai
b9b55e3d67 perf: 添加常用工具 2021-09-06 18:20:30 +08:00
feng626
900fc4420c perf: 只保留app asset flow 2021-09-06 18:19:47 +08:00
feng626
0a3e5aed56 perf: 授权分类采用from_ticket字段 2021-09-06 11:03:16 +08:00
feng626
9fb6fd44d1 Merge pull request #6745 from jumpserver/pr@dev@add_authorization_rule
feat: 授权规则分类管理
2021-09-01 16:48:56 +08:00
feng626
4214b220e1 feat: 授权规则分类管理 2021-08-31 14:13:05 +08:00
feng626
ae80797ce4 fix: 修复工单迁移bug 2021-08-27 18:05:14 +08:00
feng626
d1be4a136e Merge pull request #6735 from jumpserver/pr@dev@asset_app_suggestion
feat: add app asset suggestion
2021-08-27 16:52:56 +08:00
feng626
e8e211f47c feat: add app asset suggestion 2021-08-27 16:47:36 +08:00
feng626
44044a7d99 Merge pull request #6730 from jumpserver/pr@dev@ticket_fix
perf: 优化变量名
2021-08-27 10:14:46 +08:00
feng626
5854ad1975 perf: 优化变量名 2021-08-26 18:29:02 +08:00
健健
0b1a1591f8 从 __all__ 中删除 RDPFileSerializer (#6727)
* 从 __all__ 中删除 RDPFileSerializer

RDPFileSerializer 已经被删除

Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com>
Co-authored-by: 老广 <ibuler@qq.com>
Co-authored-by: xinwen <coderWen@126.com>
Co-authored-by: Eric_Lee <xplzv@126.com>
2021-08-26 15:12:19 +08:00
ibuler
6241238b45 feat: sso支持验证mfa 2021-08-26 15:07:55 +08:00
fit2bot
0f87f05b3f feat: 工单多级审批 + 模版创建 (#6640)
* feat: 工单多级审批 + 模版创建

* feat: 工单权限处理

* fix: 工单关闭后 再审批bug

* perf: 修改一点

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
2021-08-25 19:02:50 +08:00
Jiangjie.Bai
19c63a0b19 Merge pull request #6708 from jumpserver/dev
feat:README
2021-08-20 16:52:02 +08:00
fit2bot
1fdc558ef7 feat: 修改readme (#6707)
* feat: 修改readme

* feat: 修改readme

* feat: 修改readme

* feat: 修改readme

Co-authored-by: Bai <bugatti_it@163.com>
2021-08-20 16:47:49 +08:00
ibuler
9f6e26c4db fix: 修复ws引起的redis连接增加 2021-08-20 15:23:23 +08:00
ibuler
628012a7ee perf: 修改健康监测 2021-08-20 14:33:51 +08:00
ibuler
c1579f5fe4 perf: 修改readme 2021-08-20 14:13:40 +08:00
Bai
cbe0483b46 fix: 资产mini接口返回platform、protocols 2021-08-20 14:12:59 +08:00
xinwen
10c2935df4 fix: 用户创建 500 2021-08-20 10:07:17 +08:00
951 changed files with 40066 additions and 75503 deletions

View File

@@ -6,4 +6,5 @@ tmp/*
django.db
celerybeat.pid
### Vagrant ###
.vagrant/
.vagrant/
apps/xpack/.git

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
*.mmdb filter=lfs diff=lfs merge=lfs -text
*.mo filter=lfs diff=lfs merge=lfs -text
*.ipdb filter=lfs diff=lfs merge=lfs -text

9
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,9 @@
#### What this PR does / why we need it?
#### Summary of your change
#### Please indicate you've done the following:
- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.

View File

@@ -0,0 +1,18 @@
name: Issue Close Require
on:
schedule:
- cron: "0 0 * * *"
jobs:
issue-close-require:
runs-on: ubuntu-latest
steps:
- name: need reproduce
uses: actions-cool/issues-helper@v2
with:
actions: 'close-issues'
labels: '状态:待反馈'
inactive-day: 30
body: |
您超过 30 天未反馈信息,我们将关闭该 issue如有需求您可以重新打开或者提交新的 issue。

16
.github/workflows/issue-close.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Issue Close Check
on:
issues:
types: [closed]
jobs:
issue-close-remove-labels:
runs-on: ubuntu-latest
steps:
- name: Remove labels
uses: actions-cool/issues-helper@v2
if: ${{ !github.event.issue.pull_request }}
with:
actions: 'remove-labels'
labels: '状态:待处理,状态:待反馈'

38
.github/workflows/issue-comment.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
on:
issue_comment:
types: [created]
name: Add issues workflow labels
jobs:
add-label-if-is-author:
runs-on: ubuntu-latest
if: (github.event.issue.user.id == github.event.comment.user.id) && !github.event.issue.pull_request && (github.event.issue.state == 'open')
steps:
- name: Add require handle label
uses: actions-cool/issues-helper@v2
with:
actions: 'add-labels'
labels: '状态:待处理'
- name: Remove require reply label
uses: actions-cool/issues-helper@v2
with:
actions: 'remove-labels'
labels: '状态:待反馈'
add-label-if-not-author:
runs-on: ubuntu-latest
if: (github.event.issue.user.id != github.event.comment.user.id) && !github.event.issue.pull_request && (github.event.issue.state == 'open')
steps:
- name: Add require replay label
uses: actions-cool/issues-helper@v2
with:
actions: 'add-labels'
labels: '状态:待反馈'
- name: Remove require handle label
uses: actions-cool/issues-helper@v2
with:
actions: 'remove-labels'
labels: '状态:待处理'

16
.github/workflows/issue-open.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Issue Open Check
on:
issues:
types: [opened]
jobs:
issue-open-add-labels:
runs-on: ubuntu-latest
steps:
- name: Add labels
uses: actions-cool/issues-helper@v2
if: ${{ !github.event.issue.pull_request }}
with:
actions: 'add-labels'
labels: '状态:待处理'

View File

@@ -0,0 +1,17 @@
on:
schedule:
- cron: "0 1 * * *"
name: Check recent handle issues
jobs:
check-recent-issues-not-handle:
runs-on: ubuntu-latest
steps:
- name: Check recent issues and send msg
uses: jumpserver/action-issues-alert@master
with:
hook: ${{ secrets.WECHAT_GROUP_WEB_HOOK }}
type: recent
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,17 @@
on:
schedule:
- cron: "0 9 * * 1-5"
name: Check untimely handle issues
jobs:
check-untimely-handle-issues:
runs-on: ubuntu-latest
steps:
- name: Check untimely issues and send msg
uses: jumpserver/action-issues-alert@master
with:
hook: ${{ secrets.WECHAT_GROUP_WEB_HOOK }}
type: untimely
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -20,6 +20,8 @@ jobs:
run: |
TAG=$(basename ${GITHUB_REF})
VERSION=${TAG/v/}
wget https://raw.githubusercontent.com/jumpserver/installer/master/quick_start.sh
sed -i "s@Version=.*@Version=v${VERSION}@g" quick_start.sh
echo "::set-output name=TAG::$TAG"
echo "::set-output name=VERSION::$VERSION"
- name: Create Release
@@ -31,6 +33,16 @@ jobs:
config-name: release-config.yml
version: ${{ steps.get_version.outputs.TAG }}
tag: ${{ steps.get_version.outputs.TAG }}
- name: Upload Quick Start Script
id: upload-release-quick-start-shell
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./quick_start.sh
asset_name: quick_start.sh
asset_content_type: application/text
build-and-release:
needs: create-realese
@@ -43,4 +55,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-realese.outputs.upload_url }}
upload_url: ${{ needs.create-realese.outputs.upload_url }}

23
.github/workflows/sync-gitee.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: 🔀 Sync mirror to Gitee
on:
push:
branches:
- master
- dev
create:
jobs:
mirror:
runs-on: ubuntu-latest
if: github.repository == 'jumpserver/jumpserver'
steps:
- name: mirror
continue-on-error: true
if: github.event_name == 'push' || (github.event_name == 'create' && github.event.ref_type == 'tag')
uses: wearerequired/git-mirror-action@v1
env:
SSH_PRIVATE_KEY: ${{ secrets.GITEE_SSH_PRIVATE_KEY }}
with:
source-repo: 'git@github.com:jumpserver/jumpserver.git'
destination-repo: 'git@gitee.com:jumpserver/jumpserver.git'

3
.gitignore vendored
View File

@@ -31,12 +31,13 @@ media
celerybeat.pid
django.db
celerybeat-schedule.db
data/static
docs/_build/
xpack
xpack.bak
logs/*
### Vagrant ###
.vagrant/
release/*
releashe
/apps/script.py
data/*

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

25
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,25 @@
# Contributing
## Create pull request
PR are always welcome, even if they only contain small fixes like typos or a few lines of code. If there will be a significant effort, please document it as an issue and get a discussion going before starting to work on it.
Please submit a PR broken down into small changes bit by bit. A PR consisting of a lot features and code changes may be hard to review. It is recommended to submit PRs in an incremental fashion.
This [development guideline](https://docs.jumpserver.org/zh/master/dev/rest_api/) contains information about repository structure, how to setup development environment, how to run it, and more.
Note: If you split your pull request to small changes, please make sure any of the changes goes to master will not break anything. Otherwise, it can not be merged until this feature complete.
## Report issues
It is a great way to contribute by reporting an issue. Well-written and complete bug reports are always welcome! Please open an issue and follow the template to fill in required information.
Before opening any issue, please look up the existing issues to avoid submitting a duplication.
If you find a match, you can "subscribe" to it to get notified on updates. If you have additional helpful information about the issue, please leave a comment.
When reporting issues, always include:
* Which version you are using.
* Steps to reproduce the issue.
* Snapshots or log files if needed
Because the issues are open to the public, when submitting files, be sure to remove any sensitive information, e.g. user name, password, IP address, and company name. You can
replace those parts with "REDACTED" or other strings like "****".

View File

@@ -1,43 +1,90 @@
# 编译代码
FROM python:3.8.6-slim as stage-build
FROM python:3.8-slim
MAINTAINER JumpServer Team <ibuler@qq.com>
ARG VERSION
ENV VERSION=$VERSION
WORKDIR /opt/jumpserver
ADD . .
RUN cd utils && bash -ixeu build.sh
ARG BUILD_DEPENDENCIES=" \
g++ \
make \
pkg-config"
ARG DEPENDENCIES=" \
default-libmysqlclient-dev \
freetds-dev \
libpq-dev \
libffi-dev \
libldap2-dev \
libsasl2-dev \
libxml2-dev \
libxmlsec1-dev \
libxmlsec1-openssl \
libaio-dev \
openssh-client \
sshpass"
ARG TOOLS=" \
curl \
default-mysql-client \
iproute2 \
iputils-ping \
locales \
procps \
redis-tools \
telnet \
vim \
unzip \
wget"
RUN sed -i 's@http://.*.debian.org@http://mirrors.ustc.edu.cn@g' /etc/apt/sources.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${TOOLS} \
&& localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& mkdir -p /root/.ssh/ \
&& echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config \
&& sed -i "s@# alias l@alias l@g" ~/.bashrc \
&& echo "set mouse-=a" > ~/.vimrc \
&& echo "no" | dpkg-reconfigure dash \
&& rm -rf /var/lib/apt/lists/*
ARG TARGETARCH
ARG ORACLE_LIB_MAJOR=19
ARG ORACLE_LIB_MINOR=10
ENV ORACLE_FILE="instantclient-basiclite-linux.${TARGETARCH:-amd64}-${ORACLE_LIB_MAJOR}.${ORACLE_LIB_MINOR}.0.0.0dbru.zip"
RUN mkdir -p /opt/oracle/ \
&& cd /opt/oracle/ \
&& wget https://download.jumpserver.org/files/oracle/${ORACLE_FILE} \
&& unzip instantclient-basiclite-linux.${TARGETARCH-amd64}-19.10.0.0.0dbru.zip \
&& mv instantclient_${ORACLE_LIB_MAJOR}_${ORACLE_LIB_MINOR} instantclient \
&& echo "/opt/oracle/instantclient" > /etc/ld.so.conf.d/oracle-instantclient.conf \
&& ldconfig \
&& rm -f ${ORACLE_FILE}
WORKDIR /tmp/build
COPY ./requirements ./requirements
# 构建运行时环境
FROM python:3.8.6-slim
ARG PIP_MIRROR=https://pypi.douban.com/simple
ENV PIP_MIRROR=$PIP_MIRROR
ARG PIP_JMS_MIRROR=https://pypi.douban.com/simple
ENV PIP_JMS_MIRROR=$PIP_JMS_MIRROR
# 因为以 jms 或者 jumpserver 开头的 mirror 上可能没有
RUN pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_MIRROR} \
&& pip install --no-cache-dir $(grep -E 'jms|jumpserver' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \
&& pip install --no-cache-dir -r requirements/requirements.txt -i ${PIP_MIRROR} \
&& rm -rf ~/.cache/pip
ARG VERSION
ENV VERSION=$VERSION
ADD . .
RUN cd utils \
&& bash -ixeu build.sh \
&& mv ../release/jumpserver /opt/jumpserver \
&& rm -rf /tmp/build \
&& echo > /opt/jumpserver/config.yml
WORKDIR /opt/jumpserver
COPY ./requirements/deb_buster_requirements.txt ./requirements/deb_buster_requirements.txt
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& apt update \
&& grep -v '^#' ./requirements/deb_buster_requirements.txt | xargs apt -y install \
&& rm -rf /var/lib/apt/lists/* \
&& localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY ./requirements/requirements.txt ./requirements/requirements.txt
RUN pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_MIRROR} \
&& pip config set global.index-url ${PIP_MIRROR} \
&& pip install --no-cache-dir $(grep 'jms' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \
&& pip install --no-cache-dir -r requirements/requirements.txt
COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver
RUN mkdir -p /root/.ssh/ \
&& echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config
RUN echo > config.yml
VOLUME /opt/jumpserver/data
VOLUME /opt/jumpserver/logs

837
LICENSE
View File

@@ -1,281 +1,622 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Version 3, 29 June 2007
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
TERMS AND CONDITIONS
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
0. Definitions.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
"This License" refers to version 3 of the GNU General Public License.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
A "covered work" means either the unmodified Program or a work based
on the Program.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
1. Source Code.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
The Corresponding Source for a work in source code form is that
same work.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
2. Basic Permissions.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
13. Use with the GNU Affero General Public License.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
14. Revised Versions of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
NO WARRANTY
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
15. Disclaimer of Warranty.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
@@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -303,37 +644,31 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -1,10 +1,13 @@
<p align="center"><a href="https://jumpserver.org"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a></p>
<p align="center">
<a href="https://jumpserver.org"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a>
</p>
<h3 align="center">多云环境下更好用的堡垒机</h3>
<p align="center">
<a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0"><img src="https://shields.io/github/license/jumpserver/jumpserver" alt="License: GPL v2"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/jumpserver/jumpserver" alt="License: GPLv3"></a>
<a href="https://shields.io/github/downloads/jumpserver/jumpserver/total"><img src="https://shields.io/github/downloads/jumpserver/jumpserver/total" alt=" release"></a>
<a href="https://hub.docker.com/u/jumpserver"><img src="https://img.shields.io/docker/pulls/jumpserver/jms_all.svg" alt="Codacy"></a>
<a href="https://github.com/jumpserver/jumpserver/commits"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jumpserver/jumpserver.svg" /></a>
<a href="https://github.com/jumpserver/jumpserver"><img src="https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
@@ -13,25 +16,39 @@
JumpServer 是全球首款开源堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 规范的运维安全审计系统。
JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。
JumpServer 使用 Python 开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。
JumpServer 使用 Python 开发,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。
JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向扩展,无资产数量及并发限制。
改变世界,从一点点开始 ...
> 如需进一步了解 JumpServer 开源项目,推荐阅读 [JumpServer 的初心和使命](https://mp.weixin.qq.com/s/S6q_2rP_9MwaVwyqLQnXzA)
### 特色优势
- 开源: 零门槛,线上快速获取和安装;
- 分布式: 轻松支持大规模并发访问;
- 无插件: 仅需浏览器,极致的 Web Terminal 使用体验;
- 多租户: 一套系统,多个子公司或部门同时使用;
- 多云支持: 一套系统,同时管理不同云上面的资产;
- 云端存储: 审计录像云端存储,永不丢失;
- 多租户: 一套系统,多个子公司和部门同时使用;
- 多应用支持: 数据库Windows远程应用Kubernetes。
### UI 展示
![UI展示](https://www.jumpserver.org/images/screenshot/1.png)
### 在线体验
- 环境地址:<https://demo.jumpserver.org/>
| :warning: 注意 |
| :--------------------------- |
| 该环境仅作体验目的使用,我们会定时清理、重置数据! |
| 请勿修改体验环境用户的密码! |
| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! |
### 快速开始
@@ -41,10 +58,15 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
- [手动安装](https://github.com/jumpserver/installer)
### 组件项目
- [Lina](https://github.com/jumpserver/lina) JumpServer Web UI 项目
- [Luna](https://github.com/jumpserver/luna) JumpServer Web Terminal 项目
- [KoKo](https://github.com/jumpserver/koko) JumpServer 字符协议 Connector 项目,替代原来 Python 版本的 [Coco](https://github.com/jumpserver/coco)
- [Lion](https://github.com/jumpserver/lion-release) JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/)
| 项目 | 状态 | 描述 |
| --------------------------------------------------------------------------- | ------------------- | ---------------------------------------- |
| [Lina](https://github.com/jumpserver/lina) | <a href="https://github.com/jumpserver/lina/releases"><img alt="Lina release" src="https://img.shields.io/github/release/jumpserver/lina.svg" /></a> | JumpServer Web UI 项目 |
| [Luna](https://github.com/jumpserver/luna) | <a href="https://github.com/jumpserver/luna/releases"><img alt="Luna release" src="https://img.shields.io/github/release/jumpserver/luna.svg" /></a> | JumpServer Web Terminal 项目 |
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer 字符协议 Connector 项目,替代原来 Python 版本的 [Coco](https://github.com/jumpserver/coco) |
| [Lion](https://github.com/jumpserver/lion-release) | <a href="https://github.com/jumpserver/lion-release/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion-release.svg" /></a> | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) |
| [Magnus](https://github.com/jumpserver/magnus-release) | <a href="https://github.com/jumpserver/magnus-release/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/magnus-release.svg" /> | JumpServer 数据库代理 Connector 项目 |
| [Clients](https://github.com/jumpserver/clients) | <a href="https://github.com/jumpserver/clients/releases"><img alt="Clients release" src="https://img.shields.io/github/release/jumpserver/clients.svg" /> | JumpServer 客户端 项目 |
| [Installer](https://github.com/jumpserver/installer)| <a href="https://github.com/jumpserver/installer/releases"><img alt="Installer release" src="https://img.shields.io/github/release/jumpserver/installer.svg" /> | JumpServer 安装包 项目 |
### 社区
@@ -52,34 +74,20 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
#### 微信交流群
<img src="https://download.jumpserver.org/images/weixin-group.jpeg" alt="微信群二维码" width="200"/>
<img src="https://download.jumpserver.org/images/wecom-group.jpeg" alt="微信群二维码" width="200"/>
### 贡献
如果有你好的想法创意,或者帮助我们修复了 Bug, 欢迎提交 Pull Request
感谢以下贡献者,让 JumpServer 更加完善
<a href="https://github.com/jumpserver/jumpserver/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/jumpserver" />
</a>
<a href="https://github.com/jumpserver/koko/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/koko" />
</a>
<a href="https://github.com/jumpserver/lina/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/lina" />
</a>
<a href="https://github.com/jumpserver/luna/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/luna" />
</a>
<a href="https://github.com/jumpserver/jumpserver/graphs/contributors"><img src="https://opencollective.com/jumpserver/contributors.svg?width=890&button=false" /></a>
### 致谢
- [Apache Guacamole](https://guacamole.apache.org/) Web页面连接 RDP, SSH, VNC协议设备JumpServer 图形化组件 Lion 依赖
- [OmniDB](https://omnidb.org/) Web页面连接使用数据库JumpServer Web数据库依赖
- [Apache Guacamole](https://guacamole.apache.org/) Web页面连接 RDP, SSH, VNC 协议设备JumpServer 图形化组件 Lion 依赖
- [OmniDB](https://omnidb.org/) Web 页面连接使用数据库JumpServer Web 数据库依赖
### JumpServer 企业版
@@ -87,14 +95,18 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
### 案例研究
- [JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147)
- [JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882)
- [携程 JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851)
- [小红书的JumpServer堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516)
- [JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732)
- [中通快递JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708)
- [东方明珠JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687)
- [江苏农信:JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)
- [腾讯海外游戏:基于JumpServer构建游戏安全运营能力](https://blog.fit2cloud.com/?p=3704)
- [万华化学:通过JumpServer管理全球化分布式IT资产并且实现与云管平台的联动](https://blog.fit2cloud.com/?p=3504)
- [雪花啤酒:JumpServer堡垒机使用体会](https://blog.fit2cloud.com/?p=3412)
- [顺丰科技:JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147)
- [沐瞳游戏:通过JumpServer管控多项目分布式资产](https://blog.fit2cloud.com/?p=3213)
- [携程JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851)
- [大智慧JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882)
- [小红书:的JumpServer堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516)
- [中手游JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732)
- [中通快递JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708)
- [东方明珠JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687)
- [江苏农信JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)
### 安全说明
@@ -108,11 +120,10 @@ JumpServer是一款安全产品请参考 [基本安全建议](https://docs.ju
### License & Copyright
Copyright (c) 2014-2020 飞致云 FIT2CLOUD, All rights reserved.
Copyright (c) 2014-2022 飞致云 FIT2CLOUD, All rights reserved.
Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/gpl-2.0.html
https://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

View File

@@ -2,13 +2,13 @@
<h3 align="center">Open Source Bastion Host</h3>
<p align="center">
<a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0"><img src="https://shields.io/github/license/jumpserver/jumpserver" alt="License: GPL v2"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/jumpserver/jumpserver" alt="License: GPLv3"></a>
<a href="https://shields.io/github/downloads/jumpserver/jumpserver/total"><img src="https://shields.io/github/downloads/jumpserver/jumpserver/total" alt=" release"></a>
<a href="https://hub.docker.com/u/jumpserver"><img src="https://img.shields.io/docker/pulls/jumpserver/jms_all.svg" alt="Codacy"></a>
<a href="https://github.com/jumpserver/jumpserver"><img src="https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
JumpServer is the world's first open-source Bastion Host and is licensed under the GNU GPL v2.0. It is a 4A-compliant professional operation and maintenance security audit system.
JumpServer is the world's first open-source Bastion Host and is licensed under the GPLv3. It is a 4A-compliant professional operation and maintenance security audit system.
JumpServer uses Python / Django for development, follows Web 2.0 specifications, and is equipped with an industry-leading Web Terminal solution that provides a beautiful user interface and great user experience
@@ -85,10 +85,11 @@ If you find a security problem, please contact us directly
- 400-052-0755
### License & Copyright
Copyright (c) 2014-2019 Beijing Duizhan Tech, Inc., All rights reserved.
Copyright (c) 2014-2022 FIT2CLOUD Tech, Inc., All rights reserved.
Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/gpl-2.0.html
https://www.gnu.org/licenses/gpl-3.0.htmll
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

20
SECURITY.md Normal file
View File

@@ -0,0 +1,20 @@
# 安全说明
JumpServer 是一款正在成长的安全产品, 请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/) 部署安装.
如果你发现安全问题,请直接联系我们,我们携手让世界更好:
- ibuler@fit2cloud.com
- support@fit2cloud.com
- 400-052-0755
# Security Policy
JumpServer is a security product, The installation and development should follow our security tips.
## Reporting a Vulnerability
All security bugs should be reported to the contact as below:
- ibuler@fit2cloud.com
- support@fit2cloud.com
- 400-052-0755

View File

@@ -1,19 +1,14 @@
from common.permissions import IsOrgAdmin, HasQueryParamsUserAndIsCurrentOrgMember
from common.drf.api import JMSBulkModelViewSet
from ..models import LoginACL
from .. import serializers
from ..filters import LoginAclFilter
__all__ = ['LoginACLViewSet', ]
__all__ = ['LoginACLViewSet']
class LoginACLViewSet(JMSBulkModelViewSet):
queryset = LoginACL.objects.all()
filterset_fields = ('name', 'user', )
search_fields = filterset_fields
permission_classes = (IsOrgAdmin, )
filterset_class = LoginAclFilter
search_fields = ('name',)
serializer_class = serializers.LoginACLSerializer
def get_permissions(self):
if self.action in ["retrieve", "list"]:
self.permission_classes = (IsOrgAdmin, HasQueryParamsUserAndIsCurrentOrgMember)
return super().get_permissions()

View File

@@ -1,6 +1,4 @@
from orgs.mixins.api import OrgBulkModelViewSet
from common.permissions import IsOrgAdmin
from .. import models, serializers
@@ -11,5 +9,4 @@ class LoginAssetACLViewSet(OrgBulkModelViewSet):
model = models.LoginAssetACL
filterset_fields = ('name', )
search_fields = filterset_fields
permission_classes = (IsOrgAdmin, )
serializer_class = serializers.LoginAssetACLSerializer

View File

@@ -1,21 +1,23 @@
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView, RetrieveDestroyAPIView
from rest_framework.generics import CreateAPIView
from common.permissions import IsAppUser
from common.utils import reverse, lazyproperty
from orgs.utils import tmp_to_org, tmp_to_root_org
from tickets.api import GenericTicketStatusRetrieveCloseAPI
from orgs.utils import tmp_to_org
from ..models import LoginAssetACL
from .. import serializers
__all__ = ['LoginAssetCheckAPI', 'LoginAssetConfirmStatusAPI']
__all__ = ['LoginAssetCheckAPI']
class LoginAssetCheckAPI(CreateAPIView):
permission_classes = (IsAppUser, )
serializer_class = serializers.LoginAssetCheckSerializer
model = LoginAssetACL
rbac_perms = {
'POST': 'tickets.add_superticket'
}
def get_queryset(self):
return LoginAssetACL.objects.all()
def create(self, request, *args, **kwargs):
is_need_confirm, response_data = self.check_if_need_confirm()
@@ -45,10 +47,10 @@ class LoginAssetCheckAPI(CreateAPIView):
asset=self.serializer.asset,
system_user=self.serializer.system_user,
assignees=acl.reviewers.all(),
org_id=self.serializer.org.id
org_id=self.serializer.org.id,
)
confirm_status_url = reverse(
view_name='api-acls:login-asset-confirm-status',
view_name='api-tickets:super-ticket-status',
kwargs={'pk': str(ticket.id)}
)
ticket_detail_url = reverse(
@@ -57,11 +59,13 @@ class LoginAssetCheckAPI(CreateAPIView):
external=True, api_to_ui=True
)
ticket_detail_url = '{url}?type={type}'.format(url=ticket_detail_url, type=ticket.type)
ticket_assignees = ticket.current_step.ticket_assignees.all()
data = {
'check_confirm_status': {'method': 'GET', 'url': confirm_status_url},
'close_confirm': {'method': 'DELETE', 'url': confirm_status_url},
'ticket_detail_url': ticket_detail_url,
'reviewers': [str(user) for user in ticket.assignees.all()],
'reviewers': [str(ticket_assignee.assignee) for ticket_assignee in ticket_assignees],
'ticket_id': str(ticket.id)
}
return data
@@ -71,7 +75,3 @@ class LoginAssetCheckAPI(CreateAPIView):
serializer.is_valid(raise_exception=True)
return serializer
class LoginAssetConfirmStatusAPI(GenericTicketStatusRetrieveCloseAPI):
pass

View File

@@ -1,5 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
class AclsConfig(AppConfig):
name = 'acls'
verbose_name = _('Acls')

15
apps/acls/filters.py Normal file
View File

@@ -0,0 +1,15 @@
from django_filters import rest_framework as filters
from common.drf.filters import BaseFilterSet
from acls.models import LoginACL
class LoginAclFilter(BaseFilterSet):
user = filters.UUIDFilter(field_name='user_id')
user_display = filters.CharFilter(field_name='user__name')
class Meta:
model = LoginACL
fields = (
'name', 'user', 'user_display', 'action'
)

View File

@@ -0,0 +1,98 @@
# Generated by Django 3.1.12 on 2021-09-26 02:47
import django
from django.conf import settings
from django.db import migrations, models, transaction
from acls.models import LoginACL
LOGIN_CONFIRM_ZH = '登录复核'
LOGIN_CONFIRM_EN = 'Login confirm'
DEFAULT_TIME_PERIODS = [{'id': i, 'value': '00:00~00:00'} for i in range(7)]
def has_zh(name: str) -> bool:
for i in name:
if u'\u4e00' <= i <= u'\u9fff':
return True
return False
def migrate_login_confirm(apps, schema_editor):
login_acl_model = apps.get_model("acls", "LoginACL")
login_confirm_model = apps.get_model("authentication", "LoginConfirmSetting")
with transaction.atomic():
for instance in login_confirm_model.objects.filter(is_active=True):
user = instance.user
reviewers = instance.reviewers.all()
login_confirm = LOGIN_CONFIRM_ZH if has_zh(user.name) else LOGIN_CONFIRM_EN
date_created = instance.date_created.strftime('%Y-%m-%d %H:%M:%S')
if reviewers.count() == 0:
continue
data = {
'user': user,
'name': f'{user.name}-{login_confirm} ({date_created})',
'created_by': instance.created_by,
'action': LoginACL.ActionChoices.confirm,
'rules': {'ip_group': ['*'], 'time_period': DEFAULT_TIME_PERIODS}
}
instance = login_acl_model.objects.create(**data)
instance.reviewers.set(reviewers)
def migrate_ip_group(apps, schema_editor):
login_acl_model = apps.get_model("acls", "LoginACL")
updates = list()
with transaction.atomic():
for instance in login_acl_model.objects.exclude(action=LoginACL.ActionChoices.confirm):
instance.rules = {'ip_group': instance.ip_group, 'time_period': DEFAULT_TIME_PERIODS}
updates.append(instance)
login_acl_model.objects.bulk_update(updates, ['rules', ])
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('acls', '0001_initial'),
('authentication', '0004_ssotoken'),
]
operations = [
migrations.AlterField(
model_name='loginacl',
name='action',
field=models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow'), ('confirm', 'Login confirm')],
default='reject', max_length=64, verbose_name='Action'),
),
migrations.AddField(
model_name='loginacl',
name='reviewers',
field=models.ManyToManyField(blank=True, related_name='login_confirm_acls',
to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AlterField(
model_name='loginacl',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
related_name='login_acls', to=settings.AUTH_USER_MODEL, verbose_name='User'),
),
migrations.AddField(
model_name='loginacl',
name='rules',
field=models.JSONField(default=dict, verbose_name='Rule'),
),
migrations.RunPython(migrate_login_confirm),
migrations.RunPython(migrate_ip_group),
migrations.RemoveField(
model_name='loginacl',
name='ip_group',
),
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', '-date_updated', 'name'), 'verbose_name': 'Login acl'},
),
migrations.AlterModelOptions(
name='loginassetacl',
options={'ordering': ('priority', '-date_updated', 'name'), 'verbose_name': 'Login asset acl'},
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 3.1.13 on 2021-11-30 02:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('acls', '0002_auto_20210926_1047'),
]
operations = [
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', '-date_updated', 'name'), 'verbose_name': 'Login acl'},
),
migrations.AlterModelOptions(
name='loginassetacl',
options={'ordering': ('priority', '-date_updated', 'name'), 'verbose_name': 'Login asset acl'},
),
]

View File

@@ -1,8 +1,10 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .base import BaseACL, BaseACLQuerySet
from common.utils import get_request_ip, get_ip_city
from common.utils.ip import contains_ip
from common.utils.time_period import contains_time_period
from common.utils.timezone import local_now_display
class ACLManager(models.Manager):
@@ -15,43 +17,76 @@ class LoginACL(BaseACL):
class ActionChoices(models.TextChoices):
reject = 'reject', _('Reject')
allow = 'allow', _('Allow')
confirm = 'confirm', _('Login confirm')
# 条件
ip_group = models.JSONField(default=list, verbose_name=_('Login IP'))
# 用户
user = models.ForeignKey(
'users.User', on_delete=models.CASCADE, verbose_name=_('User'),
related_name='login_acls'
)
# 规则
rules = models.JSONField(default=dict, verbose_name=_('Rule'))
# 动作
action = models.CharField(
max_length=64, choices=ActionChoices.choices, default=ActionChoices.reject,
verbose_name=_('Action')
max_length=64, verbose_name=_('Action'),
choices=ActionChoices.choices, default=ActionChoices.reject
)
# 关联
user = models.ForeignKey(
'users.User', on_delete=models.CASCADE, related_name='login_acls', verbose_name=_('User')
reviewers = models.ManyToManyField(
'users.User', verbose_name=_("Reviewers"),
related_name="login_confirm_acls", blank=True
)
objects = ACLManager.from_queryset(BaseACLQuerySet)()
class Meta:
ordering = ('priority', '-date_updated', 'name')
verbose_name = _('Login acl')
def __str__(self):
return self.name
@property
def action_reject(self):
return self.action == self.ActionChoices.reject
def is_action(self, action):
return self.action == action
@property
def action_allow(self):
return self.action == self.ActionChoices.allow
@classmethod
def filter_acl(cls, user):
return user.login_acls.all().valid().distinct()
@staticmethod
def allow_user_to_login(user, ip):
acl = user.login_acls.valid().first()
if not acl:
return True
is_contained = contains_ip(ip, acl.ip_group)
if acl.action_allow and is_contained:
return True
if acl.action_reject and not is_contained:
return True
return False
def match(user, ip):
acls = LoginACL.filter_acl(user)
if not acls:
return
for acl in acls:
if acl.is_action(LoginACL.ActionChoices.confirm) and not acl.reviewers.exists():
continue
ip_group = acl.rules.get('ip_group')
time_periods = acl.rules.get('time_period')
is_contain_ip = contains_ip(ip, ip_group)
is_contain_time_period = contains_time_period(time_periods)
if is_contain_ip and is_contain_time_period:
# 满足条件,则返回
return acl
def create_confirm_ticket(self, request):
from tickets import const
from tickets.models import ApplyLoginTicket
from orgs.models import Organization
title = _('Login confirm') + ' {}'.format(self.user)
login_ip = get_request_ip(request) if request else ''
login_ip = login_ip or '0.0.0.0'
login_city = get_ip_city(login_ip)
login_datetime = local_now_display()
data = {
'title': title,
'type': const.TicketType.login_confirm,
'applicant': self.user,
'apply_login_city': login_city,
'apply_login_ip': login_ip,
'apply_login_datetime': login_datetime,
'org_id': Organization.ROOT_ID,
}
ticket = ApplyLoginTicket.objects.create(**data)
assignees = self.reviewers.all()
ticket.open_by_system(assignees)
return ticket

View File

@@ -37,6 +37,7 @@ class LoginAssetACL(BaseACL, OrgModelMixin):
class Meta:
unique_together = ('name', 'org_id')
ordering = ('priority', '-date_updated', 'name')
verbose_name = _('Login asset acl')
def __str__(self):
return self.name
@@ -83,20 +84,19 @@ class LoginAssetACL(BaseACL, OrgModelMixin):
@classmethod
def create_login_asset_confirm_ticket(cls, user, asset, system_user, assignees, org_id):
from tickets.const import TicketTypeChoices
from tickets.models import Ticket
from tickets.const import TicketType
from tickets.models import ApplyLoginAssetTicket
title = _('Login asset confirm') + ' ({})'.format(user)
data = {
'title': _('Login asset confirm') + ' ({})'.format(user),
'type': TicketTypeChoices.login_asset_confirm,
'meta': {
'apply_login_user': str(user),
'apply_login_asset': str(asset),
'apply_login_system_user': str(system_user),
},
'title': title,
'type': TicketType.login_asset_confirm,
'applicant': user,
'apply_login_user': user,
'apply_login_asset': asset,
'apply_login_system_user': system_user,
'org_id': org_id,
}
ticket = Ticket.objects.create(**data)
ticket.assignees.set(assignees)
ticket.open(applicant=user)
ticket = ApplyLoginAssetTicket.objects.create(**data)
ticket.open_by_system(assignees)
return ticket

View File

@@ -1,59 +1,56 @@
from django.utils.translation import ugettext as _
from rest_framework import serializers
from common.drf.serializers import BulkModelSerializer
from orgs.utils import current_org
from common.drf.serializers import MethodSerializer
from jumpserver.utils import has_valid_xpack_license
from ..models import LoginACL
from common.utils.ip import is_ip_address, is_ip_network, is_ip_segment
from .rules import RuleSerializer
__all__ = ['LoginACLSerializer', ]
def ip_group_child_validator(ip_group_child):
is_valid = ip_group_child == '*' \
or is_ip_address(ip_group_child) \
or is_ip_network(ip_group_child) \
or is_ip_segment(ip_group_child)
if not is_valid:
error = _('IP address invalid: `{}`').format(ip_group_child)
raise serializers.ValidationError(error)
common_help_text = _('Format for comma-delimited string, with * indicating a match all. ')
class LoginACLSerializer(BulkModelSerializer):
ip_group_help_text = _(
'Format for comma-delimited string, with * indicating a match all. '
'Such as: '
'192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 '
)
ip_group = serializers.ListField(
default=['*'], label=_('IP'), help_text=ip_group_help_text,
child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator])
)
user_display = serializers.ReadOnlyField(source='user.name', label=_('User'))
user_display = serializers.ReadOnlyField(source='user.username', label=_('Username'))
reviewers_display = serializers.SerializerMethodField(label=_('Reviewers'))
action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action'))
reviewers_amount = serializers.IntegerField(read_only=True, source='reviewers.count')
rules = MethodSerializer()
class Meta:
model = LoginACL
fields_mini = ['id', 'name']
fields_small = fields_mini + [
'priority', 'ip_group', 'action', 'action_display',
'is_active',
'date_created', 'date_updated',
'comment', 'created_by',
'priority', 'rules', 'action', 'action_display',
'is_active', 'user', 'user_display',
'date_created', 'date_updated', 'reviewers_amount',
'comment', 'created_by'
]
fields_fk = ['user', 'user_display',]
fields = fields_small + fields_fk
fields_fk = ['user', 'user_display']
fields_m2m = ['reviewers', 'reviewers_display']
fields = fields_small + fields_fk + fields_m2m
extra_kwargs = {
'priority': {'default': 50},
'is_active': {'default': True},
"reviewers": {'allow_null': False, 'required': True},
}
@staticmethod
def validate_user(user):
if user not in current_org.get_members():
error = _('The user `{}` is not in the current organization: `{}`').format(
user, current_org
)
raise serializers.ValidationError(error)
return user
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_action_choices()
def set_action_choices(self):
action = self.fields.get('action')
if not action:
return
choices = action._choices
if not has_valid_xpack_license():
choices.pop(LoginACL.ActionChoices.confirm, None)
action._choices = choices
def get_rules_serializer(self):
return RuleSerializer()
def get_reviewers_display(self, obj):
return ','.join([str(user) for user in obj.reviewers.all()])

View File

@@ -0,0 +1 @@
from .rules import *

View File

@@ -0,0 +1,35 @@
# coding: utf-8
#
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
from common.utils.ip import is_ip_address, is_ip_network, is_ip_segment
logger = get_logger(__file__)
__all__ = ['RuleSerializer', 'ip_group_child_validator', 'ip_group_help_text']
def ip_group_child_validator(ip_group_child):
is_valid = ip_group_child == '*' \
or is_ip_address(ip_group_child) \
or is_ip_network(ip_group_child) \
or is_ip_segment(ip_group_child)
if not is_valid:
error = _('IP address invalid: `{}`').format(ip_group_child)
raise serializers.ValidationError(error)
ip_group_help_text = _(
'Format for comma-delimited string, with * indicating a match all. '
'Such as: '
'192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 '
)
class RuleSerializer(serializers.Serializer):
ip_group = serializers.ListField(
default=['*'], label=_('IP'), help_text=ip_group_help_text,
child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator]))
time_period = serializers.ListField(default=[], label=_('Time Period'))

View File

@@ -12,7 +12,6 @@ router.register(r'login-asset-acls', api.LoginAssetACLViewSet, 'login-asset-acl'
urlpatterns = [
path('login-asset/check/', api.LoginAssetCheckAPI.as_view(), name='login-asset-check'),
path('login-asset-confirm/<uuid:pk>/status/', api.LoginAssetConfirmStatusAPI.as_view(), name='login-asset-confirm-status')
]
urlpatterns += router.urls

View File

@@ -1,4 +1,3 @@
from .application import *
from .account import *
from .mixin import *
from .remote_app import *

View File

@@ -2,74 +2,65 @@
#
from django_filters import rest_framework as filters
from django.db.models import F, Value, CharField
from django.db.models.functions import Concat
from django.http import Http404
from django.db.models import Q
from common.drf.filters import BaseFilterSet
from common.drf.api import JMSModelViewSet
from common.utils import unique
from perms.models import ApplicationPermission
from ..hands import IsOrgAdminOrAppUser, IsOrgAdmin, NeedMFAVerify
from common.drf.api import JMSBulkModelViewSet
from common.mixins import RecordViewLogMixin
from common.permissions import UserConfirmation
from authentication.const import ConfirmType
from rbac.permissions import RBACPermission
from assets.models import SystemUser
from ..models import Account
from .. import serializers
class AccountFilterSet(BaseFilterSet):
username = filters.CharFilter(field_name='username')
app = filters.CharFilter(field_name='applications', lookup_expr='exact')
app_name = filters.CharFilter(field_name='app_name', lookup_expr='exact')
username = filters.CharFilter(method='do_nothing')
type = filters.CharFilter(field_name='type', lookup_expr='exact')
category = filters.CharFilter(field_name='category', lookup_expr='exact')
app_display = filters.CharFilter(field_name='app_display', lookup_expr='exact')
class Meta:
model = ApplicationPermission
fields = ['type', 'category']
model = Account
fields = ['app', 'systemuser']
@property
def qs(self):
qs = super().qs
qs = self.filter_username(qs)
return qs
def filter_username(self, qs):
username = self.get_query_param('username')
if not username:
return qs
q = Q(username=username) | Q(systemuser__username=username)
qs = qs.filter(q).distinct()
return qs
class ApplicationAccountViewSet(JMSModelViewSet):
permission_classes = (IsOrgAdmin, )
search_fields = ['username', 'app_name']
class ApplicationAccountViewSet(JMSBulkModelViewSet):
model = Account
search_fields = ['username', 'app_display']
filterset_class = AccountFilterSet
filterset_fields = ['username', 'app_name', 'type', 'category']
serializer_class = serializers.ApplicationAccountSerializer
http_method_names = ['get', 'put', 'patch', 'options']
filterset_fields = ['username', 'app_display', 'type', 'category', 'app']
serializer_class = serializers.AppAccountSerializer
def get_queryset(self):
queryset = ApplicationPermission.objects\
.exclude(system_users__isnull=True) \
.exclude(applications__isnull=True) \
.annotate(uid=Concat(
'applications', Value('_'), 'system_users', output_field=CharField()
)) \
.annotate(systemuser=F('system_users')) \
.annotate(systemuser_display=F('system_users__name')) \
.annotate(username=F('system_users__username')) \
.annotate(password=F('system_users__password')) \
.annotate(app=F('applications')) \
.annotate(app_name=F("applications__name")) \
.values('username', 'password', 'systemuser', 'systemuser_display',
'app', 'app_name', 'category', 'type', 'uid', 'org_id')
return queryset
def get_object(self):
obj = self.get_queryset().filter(
uid=self.kwargs['pk']
).first()
if not obj:
raise Http404()
return obj
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset_list = unique(queryset, key=lambda x: (x['app'], x['systemuser']))
return queryset_list
@staticmethod
def filter_spm_queryset(resource_ids, queryset):
queryset = queryset.filter(uid__in=resource_ids)
queryset = Account.get_queryset()
return queryset
class ApplicationAccountSecretViewSet(ApplicationAccountViewSet):
serializer_class = serializers.ApplicationAccountSecretSerializer
permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify]
class SystemUserAppRelationViewSet(ApplicationAccountViewSet):
perm_model = SystemUser
class ApplicationAccountSecretViewSet(RecordViewLogMixin, ApplicationAccountViewSet):
serializer_class = serializers.AppAccountSecretSerializer
permission_classes = [RBACPermission, UserConfirmation.require(ConfirmType.MFA)]
http_method_names = ['get', 'options']
rbac_perms = {
'retrieve': 'applications.view_applicationaccountsecret',
'list': 'applications.view_applicationaccountsecret',
}

View File

@@ -1,31 +1,33 @@
# coding: utf-8
#
from orgs.mixins.api import OrgBulkModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from common.tree import TreeNodeSerializer
from ..hands import IsOrgAdminOrAppUser
from common.mixins.api import SuggestionMixin
from .. import serializers
from ..models import Application
__all__ = ['ApplicationViewSet']
class ApplicationViewSet(OrgBulkModelViewSet):
class ApplicationViewSet(SuggestionMixin, OrgBulkModelViewSet):
model = Application
filterset_fields = {
'name': ['exact'],
'category': ['exact'],
'category': ['exact', 'in'],
'type': ['exact', 'in'],
}
search_fields = ('name', 'type', 'category')
permission_classes = (IsOrgAdminOrAppUser,)
serializer_classes = {
'default': serializers.ApplicationSerializer,
'get_tree': TreeNodeSerializer
'default': serializers.AppSerializer,
'get_tree': TreeNodeSerializer,
'suggestion': serializers.MiniAppSerializer
}
rbac_perms = {
'get_tree': 'applications.view_application',
'match': 'applications.match_application'
}
@action(methods=['GET'], detail=False, url_path='tree')

View File

@@ -1,53 +0,0 @@
from django.utils.translation import ugettext as _
from common.tree import TreeNode
from orgs.models import Organization
from ..models import Application
__all__ = ['SerializeApplicationToTreeNodeMixin']
class SerializeApplicationToTreeNodeMixin:
@staticmethod
def filter_organizations(applications):
organization_ids = set(applications.values_list('org_id', flat=True))
organizations = [Organization.get_instance(org_id) for org_id in organization_ids]
organizations.sort(key=lambda x: x.name)
return organizations
@staticmethod
def create_root_node():
name = _('My applications')
node = TreeNode(**{
'id': 'applications',
'name': name,
'title': name,
'pId': '',
'open': True,
'isParent': True,
'meta': {
'type': 'root'
}
})
return node
def serialize_applications_with_org(self, applications):
root_node = self.create_root_node()
tree_nodes = [root_node]
organizations = self.filter_organizations(applications)
for i, org in enumerate(organizations):
# 组织节点
org_node = org.as_tree_node(pid=root_node.id)
tree_nodes.append(org_node)
org_applications = applications.filter(org_id=org.id)
count = org_applications.count()
org_node.name += '({})'.format(count)
# 各应用节点
apps_nodes = Application.create_tree_nodes(
queryset=org_applications, root_node=org_node,
show_empty=False
)
tree_nodes += apps_nodes
return tree_nodes

View File

@@ -2,10 +2,8 @@
#
from orgs.mixins import generics
from ..hands import IsAppUser
from .. import models
from ..serializers import RemoteAppConnectionInfoSerializer
from ..permissions import IsRemoteApp
__all__ = [
@@ -15,5 +13,4 @@ __all__ = [
class RemoteAppConnectionInfoApi(generics.RetrieveAPIView):
model = models.Application
permission_classes = (IsAppUser, IsRemoteApp)
serializer_class = RemoteAppConnectionInfoSerializer

View File

@@ -1,7 +1,9 @@
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.apps import AppConfig
class ApplicationsConfig(AppConfig):
name = 'applications'
verbose_name = _('Applications')

View File

@@ -1,10 +1,10 @@
# coding: utf-8
#
from django.db.models import TextChoices
from django.db import models
from django.utils.translation import ugettext_lazy as _
class AppCategory(TextChoices):
class AppCategory(models.TextChoices):
db = 'db', _('Database')
remote_app = 'remote_app', _('Remote app')
cloud = 'cloud', 'Cloud'
@@ -13,13 +13,20 @@ class AppCategory(TextChoices):
def get_label(cls, category):
return dict(cls.choices).get(category, '')
@classmethod
def is_xpack(cls, category):
return category in ['remote_app']
class AppType(TextChoices):
class AppType(models.TextChoices):
# db category
mysql = 'mysql', 'MySQL'
mariadb = 'mariadb', 'MariaDB'
oracle = 'oracle', 'Oracle'
pgsql = 'postgresql', 'PostgreSQL'
mariadb = 'mariadb', 'MariaDB'
sqlserver = 'sqlserver', 'SQLServer'
redis = 'redis', 'Redis'
mongodb = 'mongodb', 'MongoDB'
# remote-app category
chrome = 'chrome', 'Chrome'
@@ -33,8 +40,14 @@ class AppType(TextChoices):
@classmethod
def category_types_mapper(cls):
return {
AppCategory.db: [cls.mysql, cls.oracle, cls.pgsql, cls.mariadb],
AppCategory.remote_app: [cls.chrome, cls.mysql_workbench, cls.vmware_client, cls.custom],
AppCategory.db: [
cls.mysql, cls.mariadb, cls.oracle, cls.pgsql,
cls.sqlserver, cls.redis, cls.mongodb
],
AppCategory.remote_app: [
cls.chrome, cls.mysql_workbench,
cls.vmware_client, cls.custom
],
AppCategory.cloud: [cls.k8s]
}
@@ -62,6 +75,17 @@ class AppType(TextChoices):
def cloud_types(cls):
return [tp.value for tp in cls.category_types_mapper()[AppCategory.cloud]]
@classmethod
def is_xpack(cls, tp):
tp_category_mapper = cls.type_category_mapper()
category = tp_category_mapper[tp]
if AppCategory.is_xpack(category):
return True
return tp in ['oracle', 'postgresql', 'sqlserver']
class OracleVersion(models.TextChoices):
version_11g = '11g', '11g'
version_12c = '12c', '12c'
version_other = 'other', _('Other')

View File

@@ -11,5 +11,4 @@
"""
from common.permissions import IsAppUser, IsOrgAdmin, IsValidUser, IsOrgAdminOrAppUser, NeedMFAVerify
from users.models import User, UserGroup

View File

@@ -1,6 +1,6 @@
# Generated by Django 2.1.7 on 2019-05-20 11:04
import common.fields.model
import common.db.fields
from django.db import migrations, models
import django.db.models.deletion
import uuid
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=128, verbose_name='Name')),
('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'vSphere Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')),
('path', models.CharField(max_length=128, verbose_name='App path')),
('params', common.fields.model.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')),
('params', common.db.fields.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')),

View File

@@ -0,0 +1,76 @@
# Generated by Django 3.1.12 on 2021-08-26 09:07
import assets.models.base
import common.db.fields
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import simple_history.models
import uuid
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0076_delete_assetuser'),
('applications', '0009_applicationuser'),
]
operations = [
migrations.CreateModel(
name='HistoricalAccount',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')),
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')),
('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')),
('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')),
('version', models.IntegerField(default=1, verbose_name='Version')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('app', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='applications.application', verbose_name='Database')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('systemuser', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.systemuser', verbose_name='System user')),
],
options={
'verbose_name': 'historical Account',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='Account',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')),
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')),
('version', models.IntegerField(default=1, verbose_name='Version')),
('app', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='applications.application', verbose_name='Database')),
('systemuser', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser', verbose_name='System user')),
],
options={
'verbose_name': 'Account',
'unique_together': {('username', 'app', 'systemuser')},
},
bases=(models.Model, assets.models.base.AuthMixin),
),
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 3.1.12 on 2021-08-26 09:59
from django.db import migrations, transaction
from django.db.models import F
def migrate_app_account(apps, schema_editor):
db_alias = schema_editor.connection.alias
app_perm_model = apps.get_model("perms", "ApplicationPermission")
app_account_model = apps.get_model("applications", 'Account')
queryset = app_perm_model.objects \
.exclude(system_users__isnull=True) \
.exclude(applications__isnull=True) \
.annotate(systemuser=F('system_users')) \
.annotate(app=F('applications')) \
.values('app', 'systemuser', 'org_id')
accounts = []
for p in queryset:
if not p['app']:
continue
account = app_account_model(
app_id=p['app'], systemuser_id=p['systemuser'],
version=1, org_id=p['org_id']
)
accounts.append(account)
app_account_model.objects.using(db_alias).bulk_create(accounts, ignore_conflicts=True)
class Migration(migrations.Migration):
dependencies = [
('applications', '0010_appaccount_historicalappaccount'),
]
operations = [
migrations.RunPython(migrate_app_account)
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.1.13 on 2021-10-14 14:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0011_auto_20210826_1759'),
]
operations = [
migrations.AlterField(
model_name='account',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'),
),
migrations.AlterField(
model_name='historicalaccount',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.1.13 on 2021-10-26 09:11
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('applications', '0012_auto_20211014_2209'),
]
operations = [
migrations.AlterModelOptions(
name='application',
options={'ordering': ('name',), 'verbose_name': 'Application'},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.12 on 2021-11-05 08:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0013_auto_20211026_1711'),
]
operations = [
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.13 on 2022-01-12 12:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0014_auto_20211105_1605'),
]
operations = [
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 3.1.13 on 2022-01-18 06:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('applications', '0015_auto_20220112_2035'),
]
operations = [
migrations.AlterField(
model_name='account',
name='app',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='applications.application', verbose_name='Application'),
),
migrations.AlterField(
model_name='historicalaccount',
name='app',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='applications.application', verbose_name='Application'),
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.1.13 on 2022-02-17 13:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('applications', '0016_auto_20220118_1455'),
]
operations = [
migrations.AlterModelOptions(
name='account',
options={'permissions': [('view_applicationaccountsecret', 'Can view application account secret'), ('change_appplicationaccountsecret', 'Can change application account secret')], 'verbose_name': 'Application account'},
),
migrations.AlterModelOptions(
name='applicationuser',
options={'verbose_name': 'Application user'},
),
migrations.AlterModelOptions(
name='historicalaccount',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account'},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.13 on 2022-02-23 07:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0017_auto_20220217_2135'),
]
operations = [
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.1.14 on 2022-03-10 10:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('applications', '0018_auto_20220223_1539'),
]
operations = [
migrations.AlterModelOptions(
name='application',
options={'ordering': ('name',), 'permissions': [('match_application', 'Can match application')], 'verbose_name': 'Application'},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.14 on 2022-03-16 12:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0019_auto_20220310_1853'),
]
operations = [
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.1.14 on 2022-06-29 10:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0020_auto_20220316_2028'),
]
operations = [
migrations.AlterModelOptions(
name='historicalaccount',
options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account', 'verbose_name_plural': 'historical Application accounts'},
),
migrations.AlterField(
model_name='historicalaccount',
name='history_date',
field=models.DateTimeField(db_index=True),
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.2.12 on 2022-07-14 02:46
from django.db import migrations
def migrate_db_oracle_version_to_attrs(apps, schema_editor):
db_alias = schema_editor.connection.alias
model = apps.get_model("applications", "Application")
oracles = list(model.objects.using(db_alias).filter(type='oracle'))
for o in oracles:
o.attrs['version'] = '12c'
model.objects.using(db_alias).bulk_update(oracles, ['attrs'])
class Migration(migrations.Migration):
dependencies = [
('applications', '0021_auto_20220629_1826'),
]
operations = [
migrations.RunPython(migrate_db_oracle_version_to_attrs)
]

View File

@@ -0,0 +1,48 @@
# Generated by Django 3.1.14 on 2022-07-15 07:56
import time
from collections import defaultdict
from django.db import migrations
def migrate_account_dirty_data(apps, schema_editor):
db_alias = schema_editor.connection.alias
account_model = apps.get_model('applications', 'Account')
count = 0
bulk_size = 1000
while True:
accounts = account_model.objects.using(db_alias) \
.filter(org_id='')[count:count + bulk_size]
if not accounts:
break
accounts = list(accounts)
start = time.time()
for i in accounts:
if i.app:
org_id = i.app.org_id
elif i.systemuser:
org_id = i.systemuser.org_id
else:
org_id = ''
if org_id:
i.org_id = org_id
account_model.objects.bulk_update(accounts, ['org_id', ])
print("Update account org is empty: {}-{} using: {:.2f}s".format(
count, count + len(accounts), time.time() - start
))
count += len(accounts)
class Migration(migrations.Migration):
dependencies = [
('applications', '0022_auto_20220714_1046'),
]
operations = [
migrations.RunPython(migrate_account_dirty_data),
]

View File

@@ -1 +1,2 @@
from .application import *
from .account import *

View File

@@ -0,0 +1,110 @@
from django.db import models
from simple_history.models import HistoricalRecords
from django.db.models import F
from django.utils.translation import ugettext_lazy as _
from common.utils import lazyproperty
from assets.models.base import BaseUser
class Account(BaseUser):
app = models.ForeignKey(
'applications.Application', on_delete=models.CASCADE, null=True, verbose_name=_('Application')
)
systemuser = models.ForeignKey(
'assets.SystemUser', on_delete=models.CASCADE, null=True, verbose_name=_("System user")
)
version = models.IntegerField(default=1, verbose_name=_('Version'))
history = HistoricalRecords()
auth_attrs = ['username', 'password', 'private_key', 'public_key']
class Meta:
verbose_name = _('Application account')
unique_together = [('username', 'app', 'systemuser')]
permissions = [
('view_applicationaccountsecret', _('Can view application account secret')),
('change_appplicationaccountsecret', _('Can change application account secret')),
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.auth_snapshot = {}
def get_or_systemuser_attr(self, attr):
val = getattr(self, attr, None)
if val:
return val
if self.systemuser:
return getattr(self.systemuser, attr, '')
return ''
def load_auth(self):
for attr in self.auth_attrs:
value = self.get_or_systemuser_attr(attr)
self.auth_snapshot[attr] = [getattr(self, attr), value]
setattr(self, attr, value)
def unload_auth(self):
if not self.systemuser:
return
for attr, values in self.auth_snapshot.items():
origin_value, loaded_value = values
current_value = getattr(self, attr, '')
if current_value == loaded_value:
setattr(self, attr, origin_value)
def save(self, *args, **kwargs):
self.unload_auth()
instance = super().save(*args, **kwargs)
self.load_auth()
return instance
@lazyproperty
def category(self):
return self.app.category
@lazyproperty
def type(self):
return self.app.type
@lazyproperty
def attrs(self):
return self.app.attrs
@lazyproperty
def app_display(self):
return self.systemuser.name
@property
def username_display(self):
return self.get_or_systemuser_attr('username') or ''
@lazyproperty
def systemuser_display(self):
if not self.systemuser:
return ''
return str(self.systemuser)
@property
def smart_name(self):
username = self.username_display
if self.app:
app = str(self.app)
else:
app = '*'
return '{}@{}'.format(username, app)
@classmethod
def get_queryset(cls):
queryset = cls.objects.all() \
.annotate(type=F('app__type')) \
.annotate(app_display=F('app__name')) \
.annotate(systemuser_display=F('systemuser__name')) \
.annotate(category=F('app__category'))
return queryset
def __str__(self):
return self.smart_name

View File

@@ -1,12 +1,18 @@
from collections import defaultdict
from urllib.parse import urlencode, parse_qsl
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from orgs.mixins.models import OrgModelMixin
from common.mixins import CommonModelMixin
from common.tree import TreeNode
from common.utils import is_uuid
from assets.models import Asset, SystemUser
from ..const import OracleVersion
from ..utils import KubernetesTree
from .. import const
@@ -15,6 +21,14 @@ class ApplicationTreeNodeMixin:
name: str
type: str
category: str
attrs: dict
@staticmethod
def create_tree_id(pid, type, v):
i = dict(parse_qsl(pid))
i[type] = v
tree_id = urlencode(i)
return tree_id
@classmethod
def create_choice_node(cls, c, id_, pid, tp, opened=False, counts=None,
@@ -65,13 +79,15 @@ class ApplicationTreeNodeMixin:
return node
@classmethod
def create_category_tree_nodes(cls, root_node, counts=None, show_empty=True, show_count=True):
def create_category_tree_nodes(cls, pid, counts=None, show_empty=True, show_count=True):
nodes = []
categories = const.AppType.category_types_mapper().keys()
for category in categories:
i = root_node.id + '_' + category.value
if not settings.XPACK_ENABLED and const.AppCategory.is_xpack(category):
continue
i = cls.create_tree_id(pid, 'category', category.value)
node = cls.create_choice_node(
category, i, pid=root_node.id, tp='category',
category, i, pid=pid, tp='category',
counts=counts, opened=False, show_empty=show_empty,
show_count=show_count
)
@@ -81,17 +97,23 @@ class ApplicationTreeNodeMixin:
return nodes
@classmethod
def create_types_tree_nodes(cls, root_node, counts, show_empty=True, show_count=True):
def create_types_tree_nodes(cls, pid, counts, show_empty=True, show_count=True):
nodes = []
temp_pid = pid
type_category_mapper = const.AppType.type_category_mapper()
for tp in const.AppType.type_category_mapper().keys():
types = const.AppType.type_category_mapper().keys()
for tp in types:
if not settings.XPACK_ENABLED and const.AppType.is_xpack(tp):
continue
category = type_category_mapper.get(tp)
pid = root_node.id + '_' + category.value
i = root_node.id + '_' + tp.value
pid = cls.create_tree_id(pid, 'category', category.value)
i = cls.create_tree_id(pid, 'type', tp.value)
node = cls.create_choice_node(
tp, i, pid, tp='type', counts=counts, opened=False,
show_empty=show_empty, show_count=show_count
)
pid = temp_pid
if not node:
continue
nodes.append(node)
@@ -109,40 +131,69 @@ class ApplicationTreeNodeMixin:
return counts
@classmethod
def create_tree_nodes(cls, queryset, root_node=None, show_empty=True, show_count=True):
def create_category_type_tree_nodes(cls, queryset, pid, show_empty=True, show_count=True):
counts = cls.get_tree_node_counts(queryset)
tree_nodes = []
# 类别的节点
tree_nodes += cls.create_category_tree_nodes(
pid, counts, show_empty=show_empty,
show_count=show_count
)
# 类型的节点
tree_nodes += cls.create_types_tree_nodes(
pid, counts, show_empty=show_empty,
show_count=show_count
)
return tree_nodes
@classmethod
def create_tree_nodes(cls, queryset, root_node=None, show_empty=True, show_count=True):
tree_nodes = []
# 根节点有可能是组织名称
if root_node is None:
root_node = cls.create_root_tree_node(queryset, show_count=show_count)
tree_nodes.append(root_node)
# 类别的节点
tree_nodes += cls.create_category_tree_nodes(
root_node, counts, show_empty=show_empty,
show_count=show_count
)
# 类型的节点
tree_nodes += cls.create_types_tree_nodes(
root_node, counts, show_empty=show_empty,
show_count=show_count
tree_nodes += cls.create_category_type_tree_nodes(
queryset, root_node.id, show_empty=show_empty, show_count=show_count
)
# 应用的节点
for app in queryset:
pid = root_node.id + '_' + app.type
tree_nodes.append(app.as_tree_node(pid))
if not settings.XPACK_ENABLED and const.AppType.is_xpack(app.type):
continue
node = app.as_tree_node(root_node.id)
tree_nodes.append(node)
return tree_nodes
def as_tree_node(self, pid):
def create_app_tree_pid(self, root_id):
pid = self.create_tree_id(root_id, 'category', self.category)
pid = self.create_tree_id(pid, 'type', self.type)
return pid
def as_tree_node(self, pid, k8s_as_tree=False):
if self.type == const.AppType.k8s and k8s_as_tree:
node = KubernetesTree(pid).as_tree_node(self)
else:
node = self._as_tree_node(pid)
return node
def _attrs_to_tree(self):
if self.category == const.AppCategory.db:
return self.attrs
return {}
def _as_tree_node(self, pid):
icon_skin_category_mapper = {
'remote_app': 'chrome',
'db': 'database',
'cloud': 'cloud'
}
icon_skin = icon_skin_category_mapper.get(self.category, 'file')
pid = self.create_app_tree_pid(pid)
node = TreeNode(**{
'id': str(self.id),
'name': self.name,
@@ -156,6 +207,7 @@ class ApplicationTreeNodeMixin:
'data': {
'category': self.category,
'type': self.type,
'attrs': self._attrs_to_tree()
}
}
})
@@ -163,6 +215,8 @@ class ApplicationTreeNodeMixin:
class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin):
APP_TYPE = const.AppType
name = models.CharField(max_length=128, verbose_name=_('Name'))
category = models.CharField(
max_length=16, choices=const.AppCategory.choices, verbose_name=_('Category')
@@ -180,8 +234,12 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin):
)
class Meta:
verbose_name = _('Application')
unique_together = [('org_id', 'name')]
ordering = ('name',)
permissions = [
('match_application', _('Can match application')),
]
def __str__(self):
category_display = self.get_category_display()
@@ -192,6 +250,17 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin):
def category_remote_app(self):
return self.category == const.AppCategory.remote_app.value
@property
def category_cloud(self):
return self.category == const.AppCategory.cloud.value
@property
def category_db(self):
return self.category == const.AppCategory.db.value
def is_type(self, tp):
return self.type == tp
def get_rdp_remote_app_setting(self):
from applications.serializers.attrs import get_serializer_class_by_application_type
if not self.category_remote_app:
@@ -217,14 +286,35 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin):
'parameters': parameters
}
def get_remote_app_asset(self):
def get_remote_app_asset(self, raise_exception=True):
asset_id = self.attrs.get('asset')
if not asset_id:
if is_uuid(asset_id):
return Asset.objects.filter(id=asset_id).first()
if raise_exception:
raise ValueError("Remote App not has asset attr")
asset = Asset.objects.filter(id=asset_id).first()
return asset
def get_target_ip(self):
target_ip = ''
if self.category_remote_app:
asset = self.get_remote_app_asset()
target_ip = asset.ip if asset else target_ip
elif self.category_cloud:
target_ip = self.attrs.get('cluster')
elif self.category_db:
target_ip = self.attrs.get('host')
return target_ip
def get_target_protocol_for_oracle(self):
""" Oracle 类型需要单独处理,因为要携带版本号 """
if not self.is_type(self.APP_TYPE.oracle):
return
version = self.attrs.get('version', OracleVersion.version_12c)
if version == OracleVersion.version_other:
return
return 'oracle_%s' % version
class ApplicationUser(SystemUser):
class Meta:
proxy = True
verbose_name = _('Application user')

View File

@@ -1,38 +1,54 @@
# coding: utf-8
#
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from orgs.models import Organization
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from common.drf.serializers import MethodSerializer
from .attrs import category_serializer_classes_mapping, type_serializer_classes_mapping
from assets.serializers.base import AuthSerializerMixin
from common.drf.serializers import MethodSerializer, SecretReadableMixin
from .attrs import (
category_serializer_classes_mapping,
type_serializer_classes_mapping,
type_secret_serializer_classes_mapping
)
from .. import models
from .. import const
__all__ = [
'ApplicationSerializer', 'ApplicationSerializerMixin',
'ApplicationAccountSerializer', 'ApplicationAccountSecretSerializer'
'AppSerializer', 'MiniAppSerializer', 'AppSerializerMixin',
'AppAccountSerializer', 'AppAccountSecretSerializer', 'AppAccountBackUpSerializer'
]
class ApplicationSerializerMixin(serializers.Serializer):
class AppSerializerMixin(serializers.Serializer):
attrs = MethodSerializer()
def get_attrs_serializer(self):
default_serializer = serializers.Serializer(read_only=True)
@property
def app(self):
if isinstance(self.instance, models.Application):
_type = self.instance.type
_category = self.instance.category
instance = self.instance
else:
_type = self.context['request'].query_params.get('type')
_category = self.context['request'].query_params.get('category')
instance = None
return instance
if _type:
serializer_class = type_serializer_classes_mapping.get(_type)
elif _category:
serializer_class = category_serializer_classes_mapping.get(_category)
def get_attrs_serializer(self):
instance = self.app
tp = getattr(self, 'tp', None)
default_serializer = serializers.Serializer(read_only=True)
if not tp:
if instance:
tp = instance.type
category = instance.category
else:
tp = self.context['request'].query_params.get('type')
category = self.context['request'].query_params.get('category')
if tp:
if isinstance(self, AppAccountBackUpSerializer):
serializer_class = type_secret_serializer_classes_mapping.get(tp)
else:
serializer_class = type_serializer_classes_mapping.get(tp)
elif category:
serializer_class = category_serializer_classes_mapping.get(category)
else:
serializer_class = default_serializer
@@ -45,8 +61,14 @@ class ApplicationSerializerMixin(serializers.Serializer):
serializer = serializer_class
return serializer
def create(self, validated_data):
return super().create(validated_data)
class ApplicationSerializer(ApplicationSerializerMixin, BulkOrgResourceModelSerializer):
def update(self, instance, validated_data):
return super().update(instance, validated_data)
class AppSerializer(AppSerializerMixin, BulkOrgResourceModelSerializer):
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category display'))
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
@@ -69,42 +91,94 @@ class ApplicationSerializer(ApplicationSerializerMixin, BulkOrgResourceModelSeri
return _attrs
class ApplicationAccountSerializer(serializers.Serializer):
id = serializers.ReadOnlyField(label=_("Id"), source='uid')
username = serializers.ReadOnlyField(label=_("Username"))
password = serializers.CharField(write_only=True, label=_("Password"))
systemuser = serializers.ReadOnlyField(label=_('System user'))
systemuser_display = serializers.ReadOnlyField(label=_("System user display"))
app = serializers.ReadOnlyField(label=_('App'))
app_name = serializers.ReadOnlyField(label=_("Application name"), read_only=True)
class MiniAppSerializer(serializers.ModelSerializer):
class Meta:
model = models.Application
fields = AppSerializer.Meta.fields_mini
class AppAccountSerializer(AppSerializerMixin, AuthSerializerMixin, BulkOrgResourceModelSerializer):
category = serializers.ChoiceField(label=_('Category'), choices=const.AppCategory.choices, read_only=True)
category_display = serializers.SerializerMethodField(label=_('Category display'))
type = serializers.ChoiceField(label=_('Type'), choices=const.AppType.choices, read_only=True)
type_display = serializers.SerializerMethodField(label=_('Type display'))
uid = serializers.ReadOnlyField(label=_("Union id"))
org_id = serializers.ReadOnlyField(label=_("Organization"))
org_name = serializers.SerializerMethodField(label=_("Org name"))
date_created = serializers.DateTimeField(label=_('Date created'), format="%Y/%m/%d %H:%M:%S", read_only=True)
date_updated = serializers.DateTimeField(label=_('Date updated'), format="%Y/%m/%d %H:%M:%S", read_only=True)
category_mapper = dict(const.AppCategory.choices)
type_mapper = dict(const.AppType.choices)
def create(self, validated_data):
pass
class Meta:
model = models.Account
fields_mini = ['id', 'username', 'version']
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
fields_other = ['date_created', 'date_updated']
fields_fk = ['systemuser', 'systemuser_display', 'app', 'app_display']
fields = fields_mini + fields_fk + fields_write_only + fields_other + [
'type', 'type_display', 'category', 'category_display', 'attrs'
]
extra_kwargs = {
'username': {'default': '', 'required': False},
'password': {'write_only': True},
'app_display': {'label': _('Application display')},
'systemuser_display': {'label': _('System User')},
'account': {'label': _('account')}
}
use_model_bulk_create = True
model_bulk_create_kwargs = {
'ignore_conflicts': True
}
def update(self, instance, validated_data):
pass
@property
def app(self):
if isinstance(self.instance, models.Account):
instance = self.instance.app
else:
instance = None
return instance
def get_category_display(self, obj):
return self.category_mapper.get(obj['category'])
return self.category_mapper.get(obj.category)
def get_type_display(self, obj):
return self.type_mapper.get(obj['type'])
return self.type_mapper.get(obj.type)
@staticmethod
def get_org_name(obj):
org = Organization.get_instance(obj['org_id'])
return org.name
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('systemuser', 'app')
return queryset
def to_representation(self, instance):
instance.load_auth()
return super().to_representation(instance)
class ApplicationAccountSecretSerializer(ApplicationAccountSerializer):
password = serializers.CharField(write_only=False, label=_("Password"))
class AppAccountSecretSerializer(SecretReadableMixin, AppAccountSerializer):
class Meta(AppAccountSerializer.Meta):
extra_kwargs = {
'password': {'write_only': False},
'private_key': {'write_only': False},
'public_key': {'write_only': False},
'app_display': {'label': _('Application display')},
'systemuser_display': {'label': _('System User')}
}
class AppAccountBackUpSerializer(AppAccountSecretSerializer):
class Meta(AppAccountSecretSerializer.Meta):
fields = [
'id', 'app_display', 'attrs', 'username', 'password', 'private_key',
'public_key', 'date_created', 'date_updated', 'version'
]
def __init__(self, *args, **kwargs):
self.tp = kwargs.pop('tp', None)
super().__init__(*args, **kwargs)
@classmethod
def setup_eager_loading(cls, queryset):
return queryset
def to_representation(self, instance):
return super(AppAccountSerializer, self).to_representation(instance)

View File

@@ -1,7 +1,6 @@
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
__all__ = ['CloudSerializer']

View File

@@ -13,3 +13,14 @@ class DBSerializer(serializers.Serializer):
database = serializers.CharField(
max_length=128, required=True, allow_null=True, label=_('Database')
)
use_ssl = serializers.BooleanField(default=False, label=_('Use SSL'))
ca_cert = serializers.CharField(
required=False, allow_null=True, label=_('CA certificate')
)
client_cert = serializers.CharField(
required=False, allow_null=True, label=_('Client certificate file')
)
cert_key = serializers.CharField(
required=False, allow_null=True, label=_('Certificate key file')
)
allow_invalid_cert = serializers.BooleanField(default=False, label=_('Allow invalid cert'))

View File

@@ -10,7 +10,6 @@ from assets.models import Asset
logger = get_logger(__file__)
__all__ = ['RemoteAppSerializer']
@@ -32,7 +31,7 @@ class ExistAssetPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
class RemoteAppSerializer(serializers.Serializer):
asset_info = serializers.SerializerMethodField()
asset_info = serializers.SerializerMethodField(label=_('Asset Info'))
asset = ExistAssetPrimaryKeyRelatedField(
queryset=Asset.objects, required=True, label=_("Asset"), allow_null=True
)

View File

@@ -3,6 +3,9 @@ from .mysql import *
from .mariadb import *
from .oracle import *
from .pgsql import *
from .sqlserver import *
from .redis import *
from .mongodb import *
from .chrome import *
from .mysql_workbench import *

View File

@@ -1,10 +1,10 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.drf.fields import EncryptedField
from ..application_category import RemoteAppSerializer
__all__ = ['ChromeSerializer']
__all__ = ['ChromeSerializer', 'ChromeSecretSerializer']
class ChromeSerializer(RemoteAppSerializer):
@@ -14,13 +14,21 @@ class ChromeSerializer(RemoteAppSerializer):
max_length=128, label=_('Application path'), default=CHROME_PATH, allow_null=True,
)
chrome_target = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Target URL'), allow_null=True,
max_length=128, allow_blank=True, required=False,
label=_('Target URL'), allow_null=True,
)
chrome_username = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Username'), allow_null=True,
max_length=128, allow_blank=True, required=False,
label=_('Chrome username'), allow_null=True,
)
chrome_password = serializers.CharField(
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'),
allow_null=True
chrome_password = EncryptedField(
max_length=128, allow_blank=True, required=False,
label=_('Chrome password'), allow_null=True
)
class ChromeSecretSerializer(ChromeSerializer):
chrome_password = EncryptedField(
max_length=128, allow_blank=True, required=False,
label=_('Chrome password'), allow_null=True, write_only=False
)

View File

@@ -1,11 +1,10 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.drf.fields import EncryptedField
from ..application_category import RemoteAppSerializer
__all__ = ['CustomSerializer']
__all__ = ['CustomSerializer', 'CustomSecretSerializer']
class CustomSerializer(RemoteAppSerializer):
@@ -18,10 +17,17 @@ class CustomSerializer(RemoteAppSerializer):
allow_null=True,
)
custom_username = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Username'),
max_length=128, allow_blank=True, required=False, label=_('Custom Username'),
allow_null=True,
)
custom_password = serializers.CharField(
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'),
allow_null=True,
custom_password = EncryptedField(
max_length=128, allow_blank=True, required=False,
label=_('Custom password'), allow_null=True,
)
class CustomSecretSerializer(RemoteAppSerializer):
custom_password = EncryptedField(
max_length=128, allow_blank=True, required=False, write_only=False,
label=_('Custom password'), allow_null=True,
)

View File

@@ -1,6 +1,5 @@
from ..application_category import CloudSerializer
__all__ = ['K8SSerializer']

View File

@@ -1,6 +1,5 @@
from .mysql import MySQLSerializer
__all__ = ['MariaDBSerializer']

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
__all__ = ['MongoDBSerializer']
class MongoDBSerializer(DBSerializer):
port = serializers.IntegerField(default=27017, label=_('Port'), allow_null=True)

View File

@@ -3,13 +3,9 @@ from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
__all__ = ['MySQLSerializer']
class MySQLSerializer(DBSerializer):
port = serializers.IntegerField(default=3306, label=_('Port'), allow_null=True)

View File

@@ -1,10 +1,10 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.drf.fields import EncryptedField
from ..application_category import RemoteAppSerializer
__all__ = ['MySQLWorkbenchSerializer']
__all__ = ['MySQLWorkbenchSerializer', 'MySQLWorkbenchSecretSerializer']
class MySQLWorkbenchSerializer(RemoteAppSerializer):
@@ -27,10 +27,17 @@ class MySQLWorkbenchSerializer(RemoteAppSerializer):
allow_null=True,
)
mysql_workbench_username = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Username'),
max_length=128, allow_blank=True, required=False, label=_('Mysql workbench username'),
allow_null=True,
)
mysql_workbench_password = serializers.CharField(
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'),
allow_null=True,
mysql_workbench_password = EncryptedField(
max_length=128, allow_blank=True, required=False,
label=_('Mysql workbench password'), allow_null=True,
)
class MySQLWorkbenchSecretSerializer(RemoteAppSerializer):
mysql_workbench_password = EncryptedField(
max_length=128, allow_blank=True, required=False, write_only=False,
label=_('Mysql workbench password'), allow_null=True,
)

View File

@@ -2,11 +2,15 @@ from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
from applications.const import OracleVersion
__all__ = ['OracleSerializer']
class OracleSerializer(DBSerializer):
version = serializers.ChoiceField(
choices=OracleVersion.choices, default=OracleVersion.version_12c,
allow_null=True, label=_('Version'),
help_text=_('Magnus currently supports only 11g and 12c connections')
)
port = serializers.IntegerField(default=1521, label=_('Port'), allow_null=True)

View File

@@ -3,10 +3,8 @@ from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
__all__ = ['PostgreSerializer']
class PostgreSerializer(DBSerializer):
port = serializers.IntegerField(default=5432, label=_('Port'), allow_null=True)

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
__all__ = ['RedisSerializer']
class RedisSerializer(DBSerializer):
port = serializers.IntegerField(default=6379, label=_('Port'), allow_null=True)

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from ..application_category import DBSerializer
__all__ = ['SQLServerSerializer']
class SQLServerSerializer(DBSerializer):
port = serializers.IntegerField(default=1433, label=_('Port'), allow_null=True)

View File

@@ -1,10 +1,10 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.drf.fields import EncryptedField
from ..application_category import RemoteAppSerializer
__all__ = ['VMwareClientSerializer']
__all__ = ['VMwareClientSerializer', 'VMwareClientSecretSerializer']
class VMwareClientSerializer(RemoteAppSerializer):
@@ -23,10 +23,17 @@ class VMwareClientSerializer(RemoteAppSerializer):
allow_null=True
)
vmware_username = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Username'),
max_length=128, allow_blank=True, required=False, label=_('Vmware username'),
allow_null=True
)
vmware_password = serializers.CharField(
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'),
allow_null=True
vmware_password = EncryptedField(
max_length=128, allow_blank=True, required=False,
label=_('Vmware password'), allow_null=True
)
class VMwareClientSecretSerializer(RemoteAppSerializer):
vmware_password = EncryptedField(
max_length=128, allow_blank=True, required=False, write_only=False,
label=_('Vmware password'), allow_null=True
)

View File

@@ -1,15 +1,15 @@
from rest_framework import serializers
import copy
from applications import const
from . import application_category, application_type
__all__ = [
'category_serializer_classes_mapping',
'type_serializer_classes_mapping',
'get_serializer_class_by_application_type',
'type_secret_serializer_classes_mapping'
]
# define `attrs` field `category serializers mapping`
# ---------------------------------------------------
@@ -28,15 +28,35 @@ type_serializer_classes_mapping = {
const.AppType.mariadb.value: application_type.MariaDBSerializer,
const.AppType.oracle.value: application_type.OracleSerializer,
const.AppType.pgsql.value: application_type.PostgreSerializer,
# remote-app
const.AppType.chrome.value: application_type.ChromeSerializer,
const.AppType.mysql_workbench.value: application_type.MySQLWorkbenchSerializer,
const.AppType.vmware_client.value: application_type.VMwareClientSerializer,
const.AppType.custom.value: application_type.CustomSerializer,
const.AppType.sqlserver.value: application_type.SQLServerSerializer,
const.AppType.redis.value: application_type.RedisSerializer,
const.AppType.mongodb.value: application_type.MongoDBSerializer,
# cloud
const.AppType.k8s.value: application_type.K8SSerializer
}
remote_app_serializer_classes_mapping = {
# remote-app
const.AppType.chrome.value: application_type.ChromeSerializer,
const.AppType.mysql_workbench.value: application_type.MySQLWorkbenchSerializer,
const.AppType.vmware_client.value: application_type.VMwareClientSerializer,
const.AppType.custom.value: application_type.CustomSerializer
}
type_serializer_classes_mapping.update(remote_app_serializer_classes_mapping)
remote_app_secret_serializer_classes_mapping = {
# remote-app
const.AppType.chrome.value: application_type.ChromeSecretSerializer,
const.AppType.mysql_workbench.value: application_type.MySQLWorkbenchSecretSerializer,
const.AppType.vmware_client.value: application_type.VMwareClientSecretSerializer,
const.AppType.custom.value: application_type.CustomSecretSerializer
}
type_secret_serializer_classes_mapping = copy.deepcopy(type_serializer_classes_mapping)
type_secret_serializer_classes_mapping.update(remote_app_secret_serializer_classes_mapping)
def get_serializer_class_by_application_type(_application_type):
return type_serializer_classes_mapping.get(_application_type)

View File

@@ -11,6 +11,7 @@ app_name = 'applications'
router = BulkRouter()
router.register(r'applications', api.ApplicationViewSet, 'application')
router.register(r'accounts', api.ApplicationAccountViewSet, 'application-account')
router.register(r'system-users-apps-relations', api.SystemUserAppRelationViewSet, 'system-users-apps-relation')
router.register(r'account-secrets', api.ApplicationAccountSecretViewSet, 'application-account-secret')

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
#
from .kubernetes_util import *

View File

@@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
from urllib3.exceptions import MaxRetryError
from urllib.parse import urlencode
from kubernetes.client import api_client
from kubernetes.client.api import core_v1_api
from kubernetes import client
from kubernetes.client.exceptions import ApiException
from rest_framework.generics import get_object_or_404
from common.utils import get_logger
from common.tree import TreeNode
from assets.models import SystemUser
from .. import const
logger = get_logger(__file__)
class KubernetesClient:
def __init__(self, url, token):
self.url = url
self.token = token
def get_api(self):
configuration = client.Configuration()
configuration.host = self.url
configuration.verify_ssl = False
configuration.api_key = {"authorization": "Bearer " + self.token}
c = api_client.ApiClient(configuration=configuration)
api = core_v1_api.CoreV1Api(c)
return api
def get_namespace_list(self):
api = self.get_api()
namespace_list = []
for ns in api.list_namespace().items:
namespace_list.append(ns.metadata.name)
return namespace_list
def get_services(self):
api = self.get_api()
ret = api.list_service_for_all_namespaces(watch=False)
for i in ret.items:
print("%s \t%s \t%s \t%s \t%s \n" % (
i.kind, i.metadata.namespace, i.metadata.name, i.spec.cluster_ip, i.spec.ports))
def get_pod_info(self, namespace, pod):
api = self.get_api()
resp = api.read_namespaced_pod(namespace=namespace, name=pod)
return resp
def get_pod_logs(self, namespace, pod):
api = self.get_api()
log_content = api.read_namespaced_pod_log(pod, namespace, pretty=True, tail_lines=200)
return log_content
def get_pods(self):
api = self.get_api()
try:
ret = api.list_pod_for_all_namespaces(watch=False, _request_timeout=(3, 3))
except MaxRetryError:
logger.warning('Kubernetes connection timed out')
return
except ApiException as e:
if e.status == 401:
logger.warning('Kubernetes User not authenticated')
else:
logger.warning(e)
return
data = {}
for i in ret.items:
namespace = i.metadata.namespace
pod_info = {
'pod_name': i.metadata.name,
'containers': [j.name for j in i.spec.containers]
}
if namespace in data:
data[namespace].append(pod_info)
else:
data[namespace] = [pod_info, ]
return data
@staticmethod
def get_kubernetes_data(app_id, system_user_id):
from ..models import Application
app = get_object_or_404(Application, id=app_id)
system_user = get_object_or_404(SystemUser, id=system_user_id)
k8s = KubernetesClient(app.attrs['cluster'], system_user.token)
return k8s.get_pods()
class KubernetesTree:
def __init__(self, tree_id):
self.tree_id = tree_id
def as_tree_node(self, app):
pid = app.create_app_tree_pid(self.tree_id)
app_id = str(app.id)
parent_info = {'app_id': app_id}
node = self.create_tree_node(
app_id, pid, app.name, 'k8s', parent_info
)
return node
def as_system_user_tree_node(self, system_user, parent_info):
from ..models import ApplicationTreeNodeMixin
system_user_id = str(system_user.id)
username = system_user.username
username = username if username else '*'
name = f'{system_user.name}({username})'
pid = urlencode({'app_id': self.tree_id})
i = ApplicationTreeNodeMixin.create_tree_id(pid, 'system_user_id', system_user_id)
parent_info.update({'system_user_id': system_user_id})
node = self.create_tree_node(
i, pid, name, 'system_user', parent_info, icon='user-tie'
)
return node
def as_namespace_pod_tree_node(self, name, meta, type, counts=0, is_container=False):
from ..models import ApplicationTreeNodeMixin
i = ApplicationTreeNodeMixin.create_tree_id(self.tree_id, type, name)
meta.update({type: name})
name = name if is_container else f'{name}({counts})'
node = self.create_tree_node(
i, self.tree_id, name, type, meta, icon='cloud', is_container=is_container
)
return node
@staticmethod
def create_tree_node(id_, pid, name, identity, parent_info, icon='', is_container=False):
node = TreeNode(**{
'id': id_,
'name': name,
'title': name,
'pId': pid,
'isParent': not is_container,
'open': False,
'iconSkin': icon,
'parentInfo': urlencode(parent_info),
'meta': {
'type': 'application',
'data': {
'category': const.AppCategory.cloud,
'type': const.AppType.k8s,
'identity': identity
}
}
})
return node
def async_tree_node(self, parent_info):
pod_name = parent_info.get('pod')
app_id = parent_info.get('app_id')
namespace = parent_info.get('namespace')
system_user_id = parent_info.get('system_user_id')
tree_nodes = []
data = KubernetesClient.get_kubernetes_data(app_id, system_user_id)
if not data:
return tree_nodes
if pod_name:
for container in next(
filter(
lambda x: x['pod_name'] == pod_name, data[namespace]
)
)['containers']:
container_node = self.as_namespace_pod_tree_node(
container, parent_info, 'container', is_container=True
)
tree_nodes.append(container_node)
elif namespace:
for pod in data[namespace]:
pod_nodes = self.as_namespace_pod_tree_node(
pod['pod_name'], parent_info, 'pod', len(pod['containers'])
)
tree_nodes.append(pod_nodes)
elif system_user_id:
for namespace, pods in data.items():
namespace_node = self.as_namespace_pod_tree_node(
namespace, parent_info, 'namespace', len(pods)
)
tree_nodes.append(namespace_node)
return tree_nodes

View File

@@ -10,3 +10,5 @@ from .domain import *
from .cmd_filter import *
from .gathered_user import *
from .favorite_asset import *
from .account_backup import *
from .account_history import *

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
#
from rest_framework import status, viewsets
from rest_framework.response import Response
from orgs.mixins.api import OrgBulkModelViewSet
from .. import serializers
from ..tasks import execute_account_backup_plan
from ..models import (
AccountBackupPlan, AccountBackupPlanExecution
)
__all__ = [
'AccountBackupPlanViewSet', 'AccountBackupPlanExecutionViewSet'
]
class AccountBackupPlanViewSet(OrgBulkModelViewSet):
model = AccountBackupPlan
filter_fields = ('name',)
search_fields = filter_fields
ordering_fields = ('name',)
ordering = ('name',)
serializer_class = serializers.AccountBackupPlanSerializer
class AccountBackupPlanExecutionViewSet(viewsets.ModelViewSet):
serializer_class = serializers.AccountBackupPlanExecutionSerializer
search_fields = ('trigger',)
filterset_fields = ('trigger', 'plan_id')
http_method_names = ['get', 'post', 'options']
def get_queryset(self):
queryset = AccountBackupPlanExecution.objects.all()
return queryset
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
pid = serializer.data.get('plan')
task = execute_account_backup_plan.delay(
pid=pid, trigger=AccountBackupPlanExecution.Trigger.manual
)
return Response({'task': task.id}, status=status.HTTP_201_CREATED)
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = queryset.order_by('-date_start')
return queryset

View File

@@ -0,0 +1,50 @@
from django.db.models import F
from assets.api.accounts import (
AccountFilterSet, AccountViewSet, AccountSecretsViewSet
)
from common.mixins import RecordViewLogMixin
from .. import serializers
from ..models import AuthBook
__all__ = ['AccountHistoryViewSet', 'AccountHistorySecretsViewSet']
class AccountHistoryFilterSet(AccountFilterSet):
class Meta:
model = AuthBook.history.model
fields = AccountFilterSet.Meta.fields
class AccountHistoryViewSet(AccountViewSet):
model = AuthBook.history.model
filterset_class = AccountHistoryFilterSet
serializer_classes = {
'default': serializers.AccountHistorySerializer,
}
rbac_perms = {
'list': 'assets.view_assethistoryaccount',
'retrieve': 'assets.view_assethistoryaccount',
}
http_method_names = ['get', 'options']
def get_queryset(self):
queryset = self.model.objects.all() \
.annotate(ip=F('asset__ip')) \
.annotate(hostname=F('asset__hostname')) \
.annotate(platform=F('asset__platform__name')) \
.annotate(protocols=F('asset__protocols'))
return queryset
class AccountHistorySecretsViewSet(RecordViewLogMixin, AccountHistoryViewSet):
serializer_classes = {
'default': serializers.AccountHistorySecretSerializer
}
http_method_names = ['get']
permission_classes = AccountSecretsViewSet.permission_classes
rbac_perms = {
'list': 'assets.view_assethistoryaccountsecret',
'retrieve': 'assets.view_assethistoryaccountsecret',
}

View File

@@ -1,18 +1,21 @@
from django.db.models import F, Q
from rest_framework.decorators import action
from django_filters import rest_framework as filters
from rest_framework.response import Response
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django_filters import rest_framework as filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from orgs.mixins.api import OrgBulkModelViewSet
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, NeedMFAVerify
from rbac.permissions import RBACPermission
from common.drf.filters import BaseFilterSet
from common.mixins import RecordViewLogMixin
from common.permissions import UserConfirmation
from authentication.const import ConfirmType
from ..tasks.account_connectivity import test_accounts_connectivity_manual
from ..models import AuthBook, Node
from .. import serializers
__all__ = ['AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
__all__ = ['AccountFilterSet', 'AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
class AccountFilterSet(BaseFilterSet):
@@ -26,6 +29,7 @@ class AccountFilterSet(BaseFilterSet):
qs = super().qs
qs = self.filter_username(qs)
qs = self.filter_node(qs)
qs = qs.distinct()
return qs
def filter_username(self, qs):
@@ -61,12 +65,13 @@ class AccountViewSet(OrgBulkModelViewSet):
'default': serializers.AccountSerializer,
'verify_account': serializers.AssetTaskSerializer
}
permission_classes = (IsOrgAdmin,)
rbac_perms = {
'verify_account': 'assets.test_authbook',
'partial_update': 'assets.change_assetaccountsecret',
}
def get_queryset(self):
queryset = super().get_queryset()\
.annotate(ip=F('asset__ip'))\
.annotate(hostname=F('asset__hostname'))
queryset = AuthBook.get_queryset()
return queryset
@action(methods=['post'], detail=True, url_path='verify')
@@ -76,24 +81,30 @@ class AccountViewSet(OrgBulkModelViewSet):
return Response(data={'task': task.id})
class AccountSecretsViewSet(AccountViewSet):
class AccountSecretsViewSet(RecordViewLogMixin, AccountViewSet):
"""
因为可能要导出所有账号,所以单独建立了一个 viewset
"""
serializer_classes = {
'default': serializers.AccountSecretSerializer
}
permission_classes = (IsOrgAdmin, NeedMFAVerify)
http_method_names = ['get']
permission_classes = [RBACPermission, UserConfirmation.require(ConfirmType.MFA)]
rbac_perms = {
'list': 'assets.view_assetaccountsecret',
'retrieve': 'assets.view_assetaccountsecret',
}
class AccountTaskCreateAPI(CreateAPIView):
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.AccountTaskSerializer
filterset_fields = AccountViewSet.filterset_fields
search_fields = AccountViewSet.search_fields
filterset_class = AccountViewSet.filterset_class
def check_permissions(self, request):
return request.user.has_perm('assets.test_assetconnectivity')
def get_accounts(self):
queryset = AuthBook.objects.all()
queryset = self.filter_queryset(queryset)

View File

@@ -2,9 +2,9 @@ from django.db.models import Count
from orgs.mixins.api import OrgBulkModelViewSet
from common.utils import get_logger
from ..hands import IsOrgAdmin
from ..models import SystemUser
from .. import serializers
from rbac.permissions import RBACPermission
logger = get_logger(__file__)
@@ -20,7 +20,9 @@ class AdminUserViewSet(OrgBulkModelViewSet):
filterset_fields = ("name", "username")
search_fields = filterset_fields
serializer_class = serializers.AdminUserSerializer
permission_classes = (IsOrgAdmin,)
permission_classes = (RBACPermission,)
ordering_fields = ('name',)
ordering = ('name', )
def get_queryset(self):
queryset = super().get_queryset().filter(type=SystemUser.Type.admin)

View File

@@ -1,15 +1,22 @@
# -*- coding: utf-8 -*-
#
from assets.api import FilterAssetByNodeMixin
from rest_framework.viewsets import ModelViewSet
from rest_framework.generics import RetrieveAPIView
from rest_framework.generics import RetrieveAPIView, ListAPIView
from django.shortcuts import get_object_or_404
from django.db.models import Q
from common.utils import get_logger, get_object_or_none
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, IsSuperUser
from common.mixins.api import SuggestionMixin, RenderToJsonMixin
from users.models import User, UserGroup
from users.serializers import UserSerializer, UserGroupSerializer
from users.filters import UserFilter
from perms.models import AssetPermission
from perms.serializers import AssetPermissionSerializer
from perms.filters import AssetPermissionFilter
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from ..models import Asset, Node, Platform, SystemUser
from assets.api import FilterAssetByNodeMixin
from ..models import Asset, Node, Platform, Gateway
from .. import serializers
from ..tasks import (
update_assets_hardware_info_manual, test_assets_connectivity_manual,
@@ -17,16 +24,17 @@ from ..tasks import (
)
from ..filters import FilterAssetByNodeFilterBackend, LabelFilterBackend, IpInFilterBackend
logger = get_logger(__file__)
__all__ = [
'AssetViewSet', 'AssetPlatformRetrieveApi',
'AssetGatewayListApi', 'AssetPlatformViewSet',
'AssetTaskCreateApi', 'AssetsTaskCreateApi',
'AssetPermUserListApi', 'AssetPermUserPermissionsListApi',
'AssetPermUserGroupListApi', 'AssetPermUserGroupPermissionsListApi',
]
class AssetViewSet(FilterAssetByNodeMixin, OrgBulkModelViewSet):
class AssetViewSet(SuggestionMixin, FilterAssetByNodeMixin, OrgBulkModelViewSet):
"""
API endpoint that allows Asset to be viewed or edited.
"""
@@ -41,10 +49,14 @@ class AssetViewSet(FilterAssetByNodeMixin, OrgBulkModelViewSet):
}
search_fields = ("hostname", "ip")
ordering_fields = ("hostname", "ip", "port", "cpu_cores")
ordering = ('hostname', )
serializer_classes = {
'default': serializers.AssetSerializer,
'suggestion': serializers.MiniAssetSerializer
}
rbac_perms = {
'match': 'assets.match_asset'
}
permission_classes = (IsOrgAdminOrAppUser,)
extra_filter_backends = [FilterAssetByNodeFilterBackend, LabelFilterBackend, IpInFilterBackend]
def set_assets_node(self, assets):
@@ -65,8 +77,10 @@ class AssetViewSet(FilterAssetByNodeMixin, OrgBulkModelViewSet):
class AssetPlatformRetrieveApi(RetrieveAPIView):
queryset = Platform.objects.all()
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.PlatformSerializer
rbac_perms = {
'retrieve': 'assets.view_gateway'
}
def get_object(self):
asset_pk = self.kwargs.get('pk')
@@ -74,18 +88,12 @@ class AssetPlatformRetrieveApi(RetrieveAPIView):
return asset.platform
class AssetPlatformViewSet(ModelViewSet):
class AssetPlatformViewSet(ModelViewSet, RenderToJsonMixin):
queryset = Platform.objects.all()
permission_classes = (IsSuperUser,)
serializer_class = serializers.PlatformSerializer
filterset_fields = ['name', 'base']
search_fields = ['name']
def get_permissions(self):
if self.request.method.lower() in ['get', 'options']:
self.permission_classes = (IsOrgAdmin,)
return super().get_permissions()
def check_object_permissions(self, request, obj):
if request.method.lower() in ['delete', 'put', 'patch'] and obj.internal:
self.permission_denied(
@@ -120,7 +128,6 @@ class AssetsTaskMixin:
class AssetTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView):
model = Asset
serializer_class = serializers.AssetTaskSerializer
permission_classes = (IsOrgAdmin,)
def create(self, request, *args, **kwargs):
pk = self.kwargs.get('pk')
@@ -128,15 +135,30 @@ class AssetTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView):
request.data['assets'] = [pk]
return super().create(request, *args, **kwargs)
def check_permissions(self, request):
action = request.data.get('action')
action_perm_require = {
'refresh': 'assets.refresh_assethardwareinfo',
'push_system_user': 'assets.push_assetsystemuser',
'test': 'assets.test_assetconnectivity',
'test_system_user': 'assets.test_assetconnectivity'
}
perm_required = action_perm_require.get(action)
has = self.request.user.has_perm(perm_required)
if not has:
self.permission_denied(request)
def perform_asset_task(self, serializer):
data = serializer.validated_data
action = data['action']
if action not in ['push_system_user', 'test_system_user']:
return
asset = data['asset']
system_users = data.get('system_users')
if not system_users:
system_users = asset.get_all_systemusers()
system_users = asset.get_all_system_users()
if action == 'push_system_user':
task = push_system_users_a_asset.delay(system_users, asset=asset)
elif action == 'test_system_user':
@@ -155,17 +177,134 @@ class AssetTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView):
class AssetsTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView):
model = Asset
serializer_class = serializers.AssetsTaskSerializer
permission_classes = (IsOrgAdmin,)
def check_permissions(self, request):
action = request.data.get('action')
action_perm_require = {
'refresh': 'assets.refresh_assethardwareinfo',
}
perm_required = action_perm_require.get(action)
has = self.request.user.has_perm(perm_required)
if not has:
self.permission_denied(request)
class AssetGatewayListApi(generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.GatewayWithAuthSerializer
rbac_perms = {
'list': 'assets.view_gateway'
}
def get_queryset(self):
asset_id = self.kwargs.get('pk')
asset = get_object_or_404(Asset, pk=asset_id)
if not asset.domain:
return []
return Gateway.objects.none()
queryset = asset.domain.gateways.filter(protocol='ssh')
return queryset
class BaseAssetPermUserOrUserGroupListApi(ListAPIView):
rbac_perms = {
'GET': 'perms.view_assetpermission'
}
def get_object(self):
asset_id = self.kwargs.get('pk')
asset = get_object_or_404(Asset, pk=asset_id)
return asset
def get_asset_related_perms(self):
asset = self.get_object()
nodes = asset.get_all_nodes(flat=True)
perms = AssetPermission.objects.filter(Q(assets=asset) | Q(nodes__in=nodes))
return perms
class AssetPermUserListApi(BaseAssetPermUserOrUserGroupListApi):
filterset_class = UserFilter
search_fields = ('username', 'email', 'name', 'id', 'source', 'role')
serializer_class = UserSerializer
rbac_perms = {
'GET': 'perms.view_assetpermission'
}
def get_queryset(self):
perms = self.get_asset_related_perms()
users = User.objects.filter(
Q(assetpermissions__in=perms) | Q(groups__assetpermissions__in=perms)
).distinct()
return users
class AssetPermUserGroupListApi(BaseAssetPermUserOrUserGroupListApi):
serializer_class = UserGroupSerializer
def get_queryset(self):
perms = self.get_asset_related_perms()
user_groups = UserGroup.objects.filter(assetpermissions__in=perms).distinct()
return user_groups
class BaseAssetPermUserOrUserGroupPermissionsListApiMixin(generics.ListAPIView):
model = AssetPermission
serializer_class = AssetPermissionSerializer
filterset_class = AssetPermissionFilter
search_fields = ('name',)
rbac_perms = {
'list': 'perms.view_assetpermission'
}
def get_object(self):
asset_id = self.kwargs.get('pk')
asset = get_object_or_404(Asset, pk=asset_id)
return asset
def filter_asset_related(self, queryset):
asset = self.get_object()
nodes = asset.get_all_nodes(flat=True)
perms = queryset.filter(Q(assets=asset) | Q(nodes__in=nodes))
return perms
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.filter_asset_related(queryset)
return queryset
class AssetPermUserPermissionsListApi(BaseAssetPermUserOrUserGroupPermissionsListApiMixin):
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.filter_user_related(queryset)
queryset = queryset.distinct()
return queryset
def filter_user_related(self, queryset):
user = self.get_perm_user()
user_groups = user.groups.all()
perms = queryset.filter(Q(users=user) | Q(user_groups__in=user_groups))
return perms
def get_perm_user(self):
user_id = self.kwargs.get('perm_user_id')
user = get_object_or_404(User, pk=user_id)
return user
class AssetPermUserGroupPermissionsListApi(BaseAssetPermUserOrUserGroupPermissionsListApiMixin):
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.filter_user_group_related(queryset)
queryset = queryset.distinct()
return queryset
def filter_user_group_related(self, queryset):
user_group = self.get_perm_user_group()
perms = queryset.filter(user_groups=user_group)
return perms
def get_perm_user_group(self):
user_group_id = self.kwargs.get('perm_user_group_id')
user_group = get_object_or_404(UserGroup, pk=user_group_id)
return user_group

View File

@@ -8,15 +8,11 @@ from django.shortcuts import get_object_or_404
from common.utils import reverse
from common.utils import lazyproperty
from orgs.mixins.api import OrgBulkModelViewSet
from tickets.api import GenericTicketStatusRetrieveCloseAPI
from ..hands import IsOrgAdmin, IsAppUser
from ..models import CommandFilter, CommandFilterRule
from .. import serializers
__all__ = [
'CommandFilterViewSet', 'CommandFilterRuleViewSet', 'CommandConfirmAPI',
'CommandConfirmStatusAPI'
]
@@ -24,15 +20,13 @@ class CommandFilterViewSet(OrgBulkModelViewSet):
model = CommandFilter
filterset_fields = ("name",)
search_fields = filterset_fields
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.CommandFilterSerializer
class CommandFilterRuleViewSet(OrgBulkModelViewSet):
model = CommandFilterRule
filterset_fields = ("content",)
filterset_fields = ('content',)
search_fields = filterset_fields
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.CommandFilterRuleSerializer
def get_queryset(self):
@@ -44,8 +38,10 @@ class CommandFilterRuleViewSet(OrgBulkModelViewSet):
class CommandConfirmAPI(CreateAPIView):
permission_classes = (IsAppUser, )
serializer_class = serializers.CommandConfirmSerializer
rbac_perms = {
'POST': 'tickets.add_superticket'
}
def create(self, request, *args, **kwargs):
ticket = self.create_command_confirm_ticket()
@@ -57,14 +53,14 @@ class CommandConfirmAPI(CreateAPIView):
run_command=self.serializer.data.get('run_command'),
session=self.serializer.session,
cmd_filter_rule=self.serializer.cmd_filter_rule,
org_id=self.serializer.org.id
org_id=self.serializer.org.id,
)
return ticket
@staticmethod
def get_response_data(ticket):
confirm_status_url = reverse(
view_name='api-assets:command-confirm-status',
view_name='api-tickets:super-ticket-status',
kwargs={'pk': str(ticket.id)}
)
ticket_detail_url = reverse(
@@ -73,11 +69,12 @@ class CommandConfirmAPI(CreateAPIView):
external=True, api_to_ui=True
)
ticket_detail_url = '{url}?type={type}'.format(url=ticket_detail_url, type=ticket.type)
ticket_assignees = ticket.current_step.ticket_assignees.all()
return {
'check_confirm_status': {'method': 'GET', 'url': confirm_status_url},
'close_confirm': {'method': 'DELETE', 'url': confirm_status_url},
'ticket_detail_url': ticket_detail_url,
'reviewers': [str(user) for user in ticket.assignees.all()]
'reviewers': [str(ticket_assignee.assignee) for ticket_assignee in ticket_assignees]
}
@lazyproperty
@@ -86,7 +83,3 @@ class CommandConfirmAPI(CreateAPIView):
serializer.is_valid(raise_exception=True)
return serializer
class CommandConfirmStatusAPI(GenericTicketStatusRetrieveCloseAPI):
pass

View File

@@ -6,7 +6,6 @@ from rest_framework.views import APIView, Response
from rest_framework.serializers import ValidationError
from common.utils import get_logger
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser
from orgs.mixins.api import OrgBulkModelViewSet
from ..models import Domain, Gateway
from .. import serializers
@@ -20,8 +19,9 @@ class DomainViewSet(OrgBulkModelViewSet):
model = Domain
filterset_fields = ("name", )
search_fields = filterset_fields
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.DomainSerializer
ordering_fields = ('name',)
ordering = ('name', )
def get_serializer_class(self):
if self.request.query_params.get('gateway'):
@@ -33,13 +33,15 @@ class GatewayViewSet(OrgBulkModelViewSet):
model = Gateway
filterset_fields = ("domain__name", "name", "username", "ip", "domain")
search_fields = ("domain__name", "name", "username", "ip")
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.GatewaySerializer
class GatewayTestConnectionApi(SingleObjectMixin, APIView):
permission_classes = (IsOrgAdmin,)
queryset = Gateway.objects.all()
object = None
rbac_perms = {
'POST': 'assets.test_gateway'
}
def post(self, request, *args, **kwargs):
self.object = self.get_object(Gateway.objects.all())

View File

@@ -3,7 +3,6 @@
from orgs.mixins.api import OrgModelViewSet
from assets.models import GatheredUser
from common.permissions import IsOrgAdmin
from ..serializers import GatheredUserSerializer
from ..filters import AssetRelatedByNodeFilterBackend
@@ -15,7 +14,6 @@ __all__ = ['GatheredUserViewSet']
class GatheredUserViewSet(OrgModelViewSet):
model = GatheredUser
serializer_class = GatheredUserSerializer
permission_classes = [IsOrgAdmin]
extra_filter_backends = [AssetRelatedByNodeFilterBackend]
filterset_fields = ['asset', 'username', 'present', 'asset__ip', 'asset__hostname', 'asset_id']

View File

@@ -17,7 +17,6 @@ from django.db.models import Count
from common.utils import get_logger
from orgs.mixins.api import OrgBulkModelViewSet
from ..hands import IsOrgAdmin
from ..models import Label
from .. import serializers
@@ -30,7 +29,6 @@ class LabelViewSet(OrgBulkModelViewSet):
model = Label
filterset_fields = ("name", "value")
search_fields = filterset_fields
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.LabelSerializer
def list(self, request, *args, **kwargs):

View File

@@ -24,7 +24,7 @@ class SerializeToTreeNodeMixin:
'title': _name(node),
'pId': node.parent_key,
'isParent': True,
'open': node.is_org_root(),
'open': True,
'meta': {
'data': {
"id": node.id,

View File

@@ -13,13 +13,13 @@ from django.db.models.signals import m2m_changed
from common.const.http import POST
from common.exceptions import SomeoneIsDoingThis
from common.const.signals import PRE_REMOVE, POST_REMOVE
from common.mixins.api import SuggestionMixin
from assets.models import Asset
from common.utils import get_logger, get_object_or_none
from common.tree import TreeNodeSerializer
from orgs.mixins.api import OrgModelViewSet
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from orgs.utils import current_org
from ..hands import IsOrgAdmin
from ..models import Node
from ..tasks import (
update_node_assets_hardware_info_manual,
@@ -30,7 +30,6 @@ from .. import serializers
from .mixin import SerializeToTreeNodeMixin
from assets.locks import NodeAddChildrenLock
logger = get_logger(__file__)
__all__ = [
'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi',
@@ -41,18 +40,15 @@ __all__ = [
]
class NodeViewSet(OrgModelViewSet):
class NodeViewSet(SuggestionMixin, OrgBulkModelViewSet):
model = Node
filterset_fields = ('value', 'key', 'id')
search_fields = ('value', )
permission_classes = (IsOrgAdmin,)
search_fields = ('full_value',)
serializer_class = serializers.NodeSerializer
# 仅支持根节点指直接创建子节点下的节点需要通过children接口创建
def perform_create(self, serializer):
child_key = Node.org_root().get_next_child_key()
serializer.validated_data["key"] = child_key
serializer.save()
rbac_perms = {
'match': 'assets.match_node',
'check_assets_amount_task': 'assets.change_node'
}
@action(methods=[POST], detail=False, url_path='check_assets_amount_task')
def check_assets_amount_task(self, request):
@@ -90,7 +86,6 @@ class NodeListAsTreeApi(generics.ListAPIView):
]
"""
model = Node
permission_classes = (IsOrgAdmin,)
serializer_class = TreeNodeSerializer
@staticmethod
@@ -105,8 +100,9 @@ class NodeListAsTreeApi(generics.ListAPIView):
class NodeChildrenApi(generics.ListCreateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer
search_fields = ('value',)
instance = None
is_initial = False
@@ -185,8 +181,15 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi):
"""
model = Node
def filter_queryset(self, queryset):
if not self.request.GET.get('search'):
return queryset
queryset = super().filter_queryset(queryset)
queryset = self.model.get_ancestor_queryset(queryset)
return queryset
def list(self, request, *args, **kwargs):
nodes = self.get_queryset().order_by('value')
nodes = self.filter_queryset(self.get_queryset()).order_by('value')
nodes = self.serialize_nodes(nodes, with_asset_amount=True)
assets = self.get_assets()
data = [*nodes, *assets]
@@ -204,7 +207,6 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi):
class NodeAssetsApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetSerializer
def get_queryset(self):
@@ -219,7 +221,6 @@ class NodeAssetsApi(generics.ListAPIView):
class NodeAddChildrenApi(generics.UpdateAPIView):
model = Node
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeAddChildrenSerializer
instance = None
@@ -236,7 +237,6 @@ class NodeAddChildrenApi(generics.UpdateAPIView):
class NodeAddAssetsApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer
permission_classes = (IsOrgAdmin,)
instance = None
def perform_update(self, serializer):
@@ -248,7 +248,6 @@ class NodeAddAssetsApi(generics.UpdateAPIView):
class NodeRemoveAssetsApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer
permission_classes = (IsOrgAdmin,)
instance = None
def perform_update(self, serializer):
@@ -267,7 +266,6 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
class MoveAssetsToNodeApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer
permission_classes = (IsOrgAdmin,)
instance = None
def perform_update(self, serializer):
@@ -308,9 +306,21 @@ class MoveAssetsToNodeApi(generics.UpdateAPIView):
class NodeTaskCreateApi(generics.CreateAPIView):
perm_model = Asset
model = Node
serializer_class = serializers.NodeTaskSerializer
permission_classes = (IsOrgAdmin,)
def check_permissions(self, request):
action = request.data.get('action')
action_perm_require = {
'refresh': 'assets.refresh_assethardwareinfo',
'test': 'assets.test_assetconnectivity'
}
perm_required = action_perm_require.get(action)
has = self.request.user.has_perm(perm_required)
if not has:
self.permission_denied(request)
def get_object(self):
node_id = self.kwargs.get('pk')
@@ -343,4 +353,3 @@ class NodeTaskCreateApi(generics.CreateAPIView):
else:
task = test_node_assets_connectivity_manual.delay(node)
self.set_serializer_data(serializer, task)

View File

@@ -1,13 +1,15 @@
# ~*~ coding: utf-8 ~*~
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework.decorators import action
from common.utils import get_logger
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, IsValidUser
from common.utils import get_logger, get_object_or_none
from common.permissions import IsValidUser
from common.mixins.api import SuggestionMixin
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from orgs.utils import tmp_to_root_org
from ..models import SystemUser, Asset
from ..models import SystemUser, CommandFilterRule
from .. import serializers
from ..serializers import SystemUserWithAuthInfoSerializer, SystemUserTempAuthSerializer
from ..tasks import (
@@ -15,7 +17,6 @@ from ..tasks import (
push_system_user_to_assets
)
logger = get_logger(__file__)
__all__ = [
'SystemUserViewSet', 'SystemUserAuthInfoApi', 'SystemUserAssetAuthInfoApi',
@@ -24,7 +25,7 @@ __all__ = [
]
class SystemUserViewSet(OrgBulkModelViewSet):
class SystemUserViewSet(SuggestionMixin, OrgBulkModelViewSet):
"""
System user api set, for add,delete,update,list,retrieve resource
"""
@@ -39,8 +40,41 @@ class SystemUserViewSet(OrgBulkModelViewSet):
serializer_class = serializers.SystemUserSerializer
serializer_classes = {
'default': serializers.SystemUserSerializer,
'suggestion': serializers.MiniSystemUserSerializer
}
permission_classes = (IsOrgAdminOrAppUser,)
ordering_fields = ('name', 'protocol', 'login_mode')
ordering = ('name', )
rbac_perms = {
'su_from': 'assets.view_systemuser',
'su_to': 'assets.view_systemuser',
'match': 'assets.match_systemuser'
}
@action(methods=['get'], detail=False, url_path='su-from')
def su_from(self, request, *args, **kwargs):
""" API 获取可选的 su_from 系统用户"""
queryset = self.filter_queryset(self.get_queryset())
queryset = queryset.filter(
protocol=SystemUser.Protocol.ssh, login_mode=SystemUser.LOGIN_AUTO
)
return self.get_paginate_response_if_need(queryset)
@action(methods=['get'], detail=True, url_path='su-to')
def su_to(self, request, *args, **kwargs):
""" 获取系统用户的所有 su_to 系统用户 """
pk = kwargs.get('pk')
system_user = get_object_or_404(SystemUser, pk=pk)
queryset = system_user.su_to.all()
queryset = self.filter_queryset(queryset)
return self.get_paginate_response_if_need(queryset)
def get_paginate_response_if_need(self, queryset):
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
@@ -48,8 +82,13 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
Get system user auth info
"""
model = SystemUser
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = SystemUserWithAuthInfoSerializer
rbac_perms = {
'retrieve': 'assets.view_systemusersecret',
'list': 'assets.view_systemusersecret',
'change': 'assets.change_systemuser',
'destroy': 'assets.change_systemuser',
}
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
@@ -65,14 +104,14 @@ class SystemUserTempAuthInfoApi(generics.CreateAPIView):
def create(self, request, *args, **kwargs):
serializer = super().get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
pk = kwargs.get('pk')
user = self.request.user
data = serializer.validated_data
instance_id = data.get('instance_id')
asset_or_app_id = data.get('instance_id')
with tmp_to_root_org():
instance = get_object_or_404(SystemUser, pk=pk)
instance.set_temp_auth(instance_id, user, data)
instance.set_temp_auth(asset_or_app_id, self.request.user.id, data)
return Response(serializer.data, status=201)
@@ -81,7 +120,6 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView):
Get system user with asset auth info
"""
model = SystemUser
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = SystemUserWithAuthInfoSerializer
def get_object(self):
@@ -89,7 +127,7 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView):
asset_id = self.kwargs.get('asset_id')
user_id = self.request.query_params.get("user_id")
username = self.request.query_params.get("username")
instance.load_asset_more_auth(asset_id=asset_id, user_id=user_id, username=username)
instance.load_asset_more_auth(asset_id, username, user_id)
return instance
@@ -98,20 +136,21 @@ class SystemUserAppAuthInfoApi(generics.RetrieveAPIView):
Get system user with asset auth info
"""
model = SystemUser
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = SystemUserWithAuthInfoSerializer
rbac_perms = {
'retrieve': 'assets.view_systemusersecret',
}
def get_object(self):
instance = super().get_object()
app_id = self.kwargs.get('app_id')
user_id = self.request.query_params.get("user_id")
if user_id:
instance.load_app_more_auth(app_id, user_id)
username = self.request.query_params.get("username")
instance.load_app_more_auth(app_id, username, user_id)
return instance
class SystemUserTaskApi(generics.CreateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.SystemUserTaskSerializer
def do_push(self, system_user, asset_ids=None):
@@ -133,6 +172,18 @@ class SystemUserTaskApi(generics.CreateAPIView):
pk = self.kwargs.get('pk')
return get_object_or_404(SystemUser, pk=pk)
def check_permissions(self, request):
action = request.data.get('action')
action_perm_require = {
'push': 'assets.push_assetsystemuser',
'test': 'assets.test_assetconnectivity'
}
perm_required = action_perm_require.get(action)
has = self.request.user.has_perm(perm_required)
if not has:
self.permission_denied(request)
def perform_create(self, serializer):
action = serializer.validated_data["action"]
asset = serializer.validated_data.get('asset')
@@ -156,23 +207,40 @@ class SystemUserTaskApi(generics.CreateAPIView):
class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,)
rbac_perms = {
'list': 'assets.view_commandfilterule'
}
def get_serializer_class(self):
from ..serializers import CommandFilterRuleSerializer
return CommandFilterRuleSerializer
def get_queryset(self):
pk = self.kwargs.get('pk', None)
system_user = get_object_or_404(SystemUser, pk=pk)
return system_user.cmd_filter_rules
user_id = self.request.query_params.get('user_id')
user_group_id = self.request.query_params.get('user_group_id')
system_user_id = self.kwargs.get('pk', None)
system_user = get_object_or_none(SystemUser, pk=system_user_id)
if not system_user:
system_user_id = self.request.query_params.get('system_user_id')
asset_id = self.request.query_params.get('asset_id')
application_id = self.request.query_params.get('application_id')
rules = CommandFilterRule.get_queryset(
user_id=user_id,
user_group_id=user_group_id,
system_user_id=system_user_id,
asset_id=asset_id,
application_id=application_id
)
return rules
class SystemUserAssetsListView(generics.ListAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetSimpleSerializer
filterset_fields = ("hostname", "ip")
search_fields = filterset_fields
rbac_perms = {
'list': 'assets.view_asset'
}
def get_object(self):
pk = self.kwargs.get('pk')

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
#
from collections import defaultdict
from django.db.models import F, Value
from django.db.models import F, Value, Model
from django.db.models.signals import m2m_changed
from django.db.models.functions import Concat
from common.permissions import IsOrgAdmin
from common.utils import get_logger
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import current_org
@@ -13,13 +12,15 @@ from .. import models, serializers
__all__ = [
'SystemUserAssetRelationViewSet', 'SystemUserNodeRelationViewSet',
'SystemUserUserRelationViewSet',
'SystemUserUserRelationViewSet', 'BaseRelationViewSet',
]
logger = get_logger(__name__)
class RelationMixin:
model: Model
def get_queryset(self):
queryset = self.model.objects.all()
if not current_org.is_root():
@@ -63,13 +64,13 @@ class RelationMixin:
class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet):
pass
perm_model = models.SystemUser
class SystemUserAssetRelationViewSet(BaseRelationViewSet):
perm_model = models.AuthBook
serializer_class = serializers.SystemUserAssetRelationSerializer
model = models.SystemUser.assets.through
permission_classes = (IsOrgAdmin,)
filterset_fields = [
'id', 'asset', 'systemuser',
]
@@ -95,7 +96,6 @@ class SystemUserAssetRelationViewSet(BaseRelationViewSet):
class SystemUserNodeRelationViewSet(BaseRelationViewSet):
serializer_class = serializers.SystemUserNodeRelationSerializer
model = models.SystemUser.nodes.through
permission_classes = (IsOrgAdmin,)
filterset_fields = [
'id', 'node', 'systemuser',
]
@@ -116,7 +116,6 @@ class SystemUserNodeRelationViewSet(BaseRelationViewSet):
class SystemUserUserRelationViewSet(BaseRelationViewSet):
serializer_class = serializers.SystemUserUserRelationSerializer
model = models.SystemUser.users.through
permission_classes = (IsOrgAdmin,)
filterset_fields = [
'id', 'user', 'systemuser',
]
@@ -138,4 +137,3 @@ class SystemUserUserRelationViewSet(BaseRelationViewSet):
)
)
return queryset

View File

@@ -1,11 +1,16 @@
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.apps import AppConfig
class AssetsConfig(AppConfig):
name = 'assets'
verbose_name = _('App assets')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def ready(self):
super().ready()
from . import signals_handler
from . import signal_handlers

View File

@@ -11,5 +11,4 @@
"""
from common.permissions import IsAppUser, IsOrgAdmin, IsValidUser, IsOrgAdminOrAppUser
from users.models import User, UserGroup

View File

@@ -1,7 +1,7 @@
# Generated by Django 2.1.7 on 2019-06-24 13:08
import assets.models.utils
import common.fields.model
import common.db.fields
from django.db import migrations
@@ -15,61 +15,61 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='adminuser',
name='_password',
field=common.fields.model.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
),
migrations.AlterField(
model_name='adminuser',
name='_private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='adminuser',
name='_public_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
),
migrations.AlterField(
model_name='authbook',
name='_password',
field=common.fields.model.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
),
migrations.AlterField(
model_name='authbook',
name='_private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='authbook',
name='_public_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
),
migrations.AlterField(
model_name='gateway',
name='_password',
field=common.fields.model.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
),
migrations.AlterField(
model_name='gateway',
name='_private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='gateway',
name='_public_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
),
migrations.AlterField(
model_name='systemuser',
name='_password',
field=common.fields.model.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'),
),
migrations.AlterField(
model_name='systemuser',
name='_private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='systemuser',
name='_public_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'),
),
]

View File

@@ -1,6 +1,6 @@
# Generated by Django 2.1.7 on 2019-07-11 12:18
import common.fields.model
import common.db.fields
from django.db import migrations
@@ -14,21 +14,21 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='adminuser',
name='private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='authbook',
name='private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='gateway',
name='private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
),
migrations.AlterField(
model_name='systemuser',
name='private_key',
field=common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'),
),
]

View File

@@ -1,6 +1,6 @@
# Generated by Django 2.2.7 on 2019-12-06 07:26
import common.fields.model
import common.db.fields
from django.db import migrations, models
@@ -36,7 +36,7 @@ class Migration(migrations.Migration):
('name', models.SlugField(allow_unicode=True, unique=True, verbose_name='Name')),
('base', models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=16, verbose_name='Base')),
('charset', models.CharField(choices=[('utf8', 'UTF-8'), ('gbk', 'GBK')], default='utf8', max_length=8, verbose_name='Charset')),
('meta', common.fields.model.JsonDictTextField(blank=True, null=True, verbose_name='Meta')),
('meta', common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Meta')),
('internal', models.BooleanField(default=False, verbose_name='Internal')),
('comment', models.TextField(blank=True, null=True, verbose_name='Comment')),
],

View File

@@ -1,7 +1,8 @@
# Generated by Django 3.1.6 on 2021-06-04 16:46
import uuid
from django.db import migrations, models, transaction
import django.db.models.deletion
from django.db import IntegrityError
from django.db.models import F
@@ -15,7 +16,7 @@ def migrate_admin_user_to_system_user(apps, schema_editor):
for admin_user in admin_users:
kwargs = {}
for attr in [
'id', 'org_id', 'username', 'password', 'private_key', 'public_key',
'org_id', 'username', 'password', 'private_key', 'public_key',
'comment', 'date_created', 'date_updated', 'created_by',
]:
value = getattr(admin_user, attr)
@@ -27,7 +28,16 @@ def migrate_admin_user_to_system_user(apps, schema_editor):
).exists()
if exist:
name = admin_user.name + '_' + str(admin_user.id)[:5]
i = admin_user.id
exist = system_user_model.objects.using(db_alias).filter(
id=i, org_id=admin_user.org_id
).exists()
if exist:
i = uuid.uuid4()
kwargs.update({
'id': i,
'name': name,
'type': 'admin',
'protocol': 'ssh',
@@ -36,7 +46,11 @@ def migrate_admin_user_to_system_user(apps, schema_editor):
with transaction.atomic():
s = system_user_model(**kwargs)
s.save()
try:
s.save()
except IntegrityError:
s.id = None
s.save()
print(" Migrate admin user to system user: {} => {}".format(admin_user.name, s.name))
assets = admin_user.assets.all()
s.assets.set(assets)

View File

@@ -1,6 +1,6 @@
# Generated by Django 3.1.6 on 2021-06-05 16:10
import common.fields.model
import common.db.fields
from django.conf import settings
import django.core.validators
from django.db import migrations, models
@@ -18,7 +18,7 @@ def migrate_old_authbook_to_history(apps, schema_editor):
print()
while True:
authbooks = authbook_model.objects.using(db_alias).filter(is_latest=False)[:20]
authbooks = authbook_model.objects.using(db_alias).filter(is_latest=False)[:1000]
if not authbooks:
break
historys = []
@@ -58,9 +58,9 @@ class Migration(migrations.Migration):
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')),
('password', common.fields.model.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
('private_key', common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
('public_key', common.fields.model.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')),
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')),
('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')),

Some files were not shown because too many files have changed in this diff Show More