Giter Site home page Giter Site logo

opendevops-cn / codo-admin Goto Github PK

View Code? Open in Web Editor NEW
211.0 11.0 136.0 5.85 MB

基于Tornado实现,提供Restful风格的API,提供基于RBAC的完善权限管理,可对所有用户的操作进行审计

Home Page: http://www.opendevops.cn/

License: GNU General Public License v3.0

Dockerfile 0.29% Python 99.67% Shell 0.04%
rbac admin email sms-api cms

codo-admin's Introduction

后端管理平台

更新日志

部署文档

在线访问

简介

   本应用是基于tornado框架 restful风格的API 实现后台管理,搭配使用admin-front前端(iView+ vue)组成的一套后台用户 权限以及系统管理的解决方案(提供登录,注册 密码修改 鉴权 用户管理 角色管理 权限管理 前端组件管理 前端路由管理 通知服务API 系统基础信息接口) 本项目为CODO开源项目提供后台支持,也可以基于此项目基础项目开发自己的站点,更多基础功能还在不断开发中,如果想要查看更新动态,你可以到更新日志 查看最新更新,如果你是新手想快速部署,你可以去部署文档 查看

功能

  • 登录/登出 (支持谷歌动态码/支持邮箱登录/支持LDAP登录)

  • 密码修改

  • 鉴权 /权限刷新

  • 用户管理 用户系统基于RBAC模型的

  • 角色管理

  • 权限管理 (后端路由)基于角色

  • 菜单管理 (前端路由)基于角色

  • 组件管理 (前端组件)基于角色

  • 通知管理 (提供发送短信,发送邮件API)

  • 系统配置 (后端api地址,短信配置,邮件配置,存储配置,邮箱登录等等)

  • 系统日志 (从API网关获取日志,当然也可以自行从基类获取)

结构

├── doc
│   ├── data.sql
│   ├── deployment.md
│   ├── nginx_ops.conf
│   ├── requirements.txt
│   └── supervisor_ops.conf
├── docker-compose.yml
├── Dockerfile
├── __init__.py
├── libs
│   ├── base_handler.py
│   ├── __init__.py
│   ├── my_verify.py
│   └── utils.py
├── mg
│   ├── applications.py
│   ├── handlers
│   │   ├── app_mg_handler.py
│   │   ├── app_settings_handler.py
│   │   ├── components_v4_handler.py
│   │   ├── configs_init.py
│   │   ├── functions_v4_handler.py
│   │   ├── __init__.py
│   │   ├── login_handler.py
│   │   ├── menus_v4_handler.py
│   │   ├── notifications_handler.py
│   │   ├── roles_handler.py
│   │   ├── users_v4_handler.py
│   │   └── verify_handler.py
│   ├── __init__.py
│   └── subscribe.py
├── models
│   ├── admin.py
│   ├── app_config.py
│   ├── __init__.py
├── README.md
├── settings.py
└── startup.py

展示

用户管理

这部分文档主要用来介绍用户管理,它可以很精细的管理你的用户权限 初始账户密码 admin admin@123

用户列表

用户列表:顾名思义,用来管理和展示用户的列表,记录用户的详细信息

功能支持

  • 搜索用户
  • 新建用户
  • 删除用户
  • 关闭用户
  • 重置密码
  • 重置MFA(Google Authenticator)
  • 获取令牌

展示界面

user_list

权限列表

用来详细配置管理每个接口的权限,默认不需修改。

注意事项

  • 系统默认已经配置了所有权限和方法,管理员默认拥有/权限,无需修改,以免造成系统请求某功能出错

功能说明

  • 支持多种搜索方式,如:权限名称、请求路径、请求方法、时间等

  • 支持新增、编辑、关闭、删除等操作权限的管理

  • 支持新增自定义权限功能,适用于开发人员编写的API接口能很方便的接入进来权限管理划分

  • 一些详细的API及使用文档正在支持更新中............

user_list

菜单组件

菜单组件:顾名思义,也就是导航栏所看到的功能模块(如:用户管理、系统管理)和一些功能按钮(如:编辑、删除按钮),默认无需修改

注意事项

  • 系统默认已经配置了所有菜单功能模块及组件,无需修改此项,以免造成访问出错。

功能介绍

列举以下几个菜单和组件进行介绍,字面英语也可看出含义,如下:

  • home:家目录
  • usermanage:用户管理
  • cron:定时任务
  • edit_button:编辑按钮

由于代码层面不好直接使用中文,你可以选择平台语言English,如下图,很清晰看到每个作用。

menus

角色管理

基于RBAC角色管理访问控制权限,可以很精细/方便的管理你的用户权限

功能介绍

  • 角色的搜索、编辑、关闭、删除

  • 自定义角色名字,自定义赋权组件、菜单、权限管理

  • 列表可搜索赋权设计,方便用户可视化操作

rbac

示例介绍分为两部分,创建管理员用户赋权和创建普通用户赋权

创建普通用户示例

新建用户

同上,填写信息即可,详细权限管理全部在角色管理配置

用户赋权

create_general_user

general_user_epm

创建管理员用户示例

新增用户

点击用户列表---新增用户,输入信息

create_user

用户赋权

点击角色管理---新建,输入角色信息,选择角色进行赋权

create_rbac

user_emp

user_emp02

user_emp03

系统管理

这部分主要介绍系统配置,系统管理模块主要分为:系统配置系统日志

系统配置

系统配置主要介绍系统参数配置,后续后陆续支持各种核心功能配置

系统配置

这块需要配置你的API地址,部署时你API网关服务所部署的服务器地址,只有确认了API网关,各个功能模块才可以正常通信。

  • API地址: 你的API网关地址,可以是IP/域名,必填项。 API网关部署

邮件设置

这块主要配置邮箱,配置了此邮箱信息后,后续平台内所涉及到邮件提醒都会使用此邮箱配置。

不同运营商配置可参考FAQ邮箱设置问题

  • SMTP主题: 邮件标题
  • SMTP主机: 服务器地址
  • SMTP端口: 服务器端口
  • SMTP账户: 邮箱账户名
  • SMTP密码: 邮箱账户密码
  • 如果SMTP端口是465,通常需要启用SSL
  • 如果SMTP端口是587,通常需要启用TLS
  • 点击测试邮件会给当前用户发送一封邮件用于测试

短信接口

这块主要配置短信接口信息,短信接口只支持阿里云阿里大鱼,后续平台所涉及到发短信会调用此接口

  • 短信区域: cn-hangzhou 目前阿里官方给出必须是这个
  • API名称: Dysmsapi 目前官方给出一般都是这个名称
  • API域名:dysmsapi.aliyuncs.com 目前官方给出必须是这个地址
  • KEY_ID: 你的IAM访问控制密钥ID
  • KEY_SECRET: 你的access_secret密钥,备注:这里需要必须有SMS的权限
  • 点击测试端口会给当前用户发送一条短信用于测试

邮箱登陆

这块主要是支持第三方邮箱登陆,当你想要使用邮箱登陆此平台时,你可以在此进行配置 比如我们企业邮箱是腾讯的,域名就是opendevops.cn,SMTP就是腾讯的stmp.exmail.qq.com ,这样配置完成后我就可以使用我[email protected]邮箱+密码登陆此平台了。

  • 邮箱SMTP: 这里输入你邮箱服务商的SMTP地址
  • 邮箱域名:这里是你的邮箱后缀名字

存储配置 -> 这块主要是配置Bucket信息,目前只支持阿里云的OSS,这里目前主要用于将跳板日志审计的内容存放到OSS目录里面,若不配置此项则存数据库(可能会很大)

  • 区域Region:阿里云的可用区域,如:cn-hangzhou
  • 存储桶名称: Bucket名称
  • SecretID: 密钥ID,需要有OSS权限
  • Secret Key: 密钥Key,需要有OSS权限

系统日志

这里主要记录的本系统平台的所有请求日志,如:GET/POST/DELETE/PUT等,你的操作信息都会被记录,不要随意干坏事哟,管理员都可以看到的,安全我们还是会考虑进去的。

获取TOKEN

本系统使用token进行身份验证,当用户需要API进行访问的时候就需要获取token,并把token放入cookie里或者 访问的url参数里

  • 从用户管理 > 菜单组件里面找到 get_token_btn 这个代表获取token的按钮 要存在并且启用

  • 从用户管理 >角色管理里面找到你要赋值的角色,点击组件把get_token_btn 添加进去

  • 从用户管理 > 用户列表 会看到这个长期token的按钮,如果你是超级管理员 你就可以选中用户点击,然后系统会通过邮件把这个用户的token 发送至当前用户以及被选中用户的邮箱,token 有效期为三年。强烈建议如果使用token进行操作的时候 使用单独用户,防止人员变动造成token不可用,要进行精确权限控制,做好备注,且不要给此用户菜单以及组件权限。

  • 使用token 向 CODO 服务 API 提交安全的 REST 或 HTTP 查询协议请求。为了您的安全,请不要与任何人分享您的密钥。作为最佳做法,我们建议经常更换密钥

  • 简单python示例,当然你之前一定会检查这个token是否对这个接口有权限,对吧!

import requests
import json

auth_key = '这里就是你的token'
url = 'https://xxx.xxxx.cn/api/kerrigan/v1/conf/publish/config/?project_code=shenshuo&environment=dev&service=nginx&filename=demo.conf'
### 使用 cookie 传递
try:
    res = requests.get(url, cookies=dict(auth_key=auth_key))
    ret = json.loads(res.content)
    if ret['code'] == 0: return ret['data']
except Exception as e:
    print('[Error:] 接口连接失败,错误信息:{}'.format(e))
    exit(-1)

### 使用url 传递
try:
    _params = {'这里是参数名': '这里是参数值', 'auth_key': auth_key}
    res = requests.get(url, params=_params)
    ret = json.loads(res.content)
    if ret['code'] == 0: return ret['data']
except Exception as e:
    print('[Error:] 接口连接失败,错误信息:{}'.format(e))
    exit(-2)

部署文档

项目部署

License

Everything is GPL v3.0.

codo-admin's People

Contributors

ss1917 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

codo-admin's Issues

长期token一天失效

指定用户获取长期token来调用api,测试发现token一天就会失效,和文档上描述以及邮件描述的三年有效期不符合啊,是需要单独额外配置吗,如果需要的话应该在哪配置呢,非常感谢

codo-admin启动报错

codo-admin启动后,报错,进入容器后访问容器内部9800,9801,9802端口,都提示如下错误

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/tornado/web.py", line 1676, in _execute
result = self.prepare()
File "/usr/local/lib/python3.6/site-packages/tornado/web.py", line 2431, in prepare
raise HTTPError(self._status_code)
tornado.web.HTTPError: HTTP 404: Not Found

不知道如何解决

resource_id设置默认值以及唯一索引的原因导致写入失败

resource_id = Column('resource_id', String(50), unique=True, default="rg-{}".format(uuid()))

这块设置resource_id默认值后,实际上首次运行生成一个默认值,以后会一直使用这个默认值了,所有的默认值都是这个了。然后唯一索引会导致写入失败。
我们期望的是,每次写入的时候,类似update_time的默认值一样,重新运行uuid函数,但是实际不是。

管理后端codo-admin初始化表结构报错pymysql.err.InternalError: (1046, 'No database selected')

[root@localhost codo-admin] # python3 db_sync.py
2020-12-10 16:14:06,011 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2020-12-10 16:14:06,011 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,014 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
2020-12-10 16:14:06,014 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,015 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2020-12-10 16:14:06,015 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,016 INFO sqlalchemy.engine.base.Engine show collation where Charset = 'utf8mb4' and Collation = 'utf8mb4_bin'
2020-12-10 16:14:06,016 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,018 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2020-12-10 16:14:06,018 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,018 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2020-12-10 16:14:06,018 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,019 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
2020-12-10 16:14:06,019 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,020 INFO sqlalchemy.engine.base.Engine DESCRIBE mg_app_settings
2020-12-10 16:14:06,020 INFO sqlalchemy.engine.base.Engine {}
2020-12-10 16:14:06,021 INFO sqlalchemy.engine.base.Engine ROLLBACK
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
cursor.execute(statement, parameters)
File "/usr/local/lib64/python3.6/site-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/usr/local/lib64/python3.6/site-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 517, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 732, in _read_query_result
result.read()
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 1075, in read
first_packet = self.connection._read_packet()
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 684, in _read_packet
packet.check_error()
File "/usr/local/lib64/python3.6/site-packages/pymysql/protocol.py", line 220, in check_error
err.raise_mysql_exception(self._data)
File "/usr/local/lib64/python3.6/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.InternalError: (1046, 'No database selected')

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "db_sync.py", line 42, in
create()
File "db_sync.py", line 29, in create
Base.metadata.create_all(engine)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 4287, in create_all
ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2033, in _run_visitor
conn._run_visitor(visitorcallable, element, **kwargs)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1607, in _run_visitor
visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/visitors.py", line 131, in traverse_single
return meth(obj, **kw)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/ddl.py", line 754, in visit_metadata
[t for t in tables if self._can_create_table(t)]
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/ddl.py", line 754, in
[t for t in tables if self._can_create_table(t)]
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/ddl.py", line 731, in _can_create_table
self.connection, table.name, schema=effective_schema
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/dialects/mysql/base.py", line 2335, in has_table
).execute(st)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 982, in execute
return self.execute_text(object, multiparams, params)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1155, in _execute_text
parameters,
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1248, in _execute_context
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1466, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 383, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 128, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
cursor.execute(statement, parameters)
File "/usr/local/lib64/python3.6/site-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/usr/local/lib64/python3.6/site-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 517, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 732, in _read_query_result
result.read()
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 1075, in read
first_packet = self.connection._read_packet()
File "/usr/local/lib64/python3.6/site-packages/pymysql/connections.py", line 684, in _read_packet
packet.check_error()
File "/usr/local/lib64/python3.6/site-packages/pymysql/protocol.py", line 220, in check_error
err.raise_mysql_exception(self._data)
File "/usr/local/lib64/python3.6/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
raise errorclass(errno, errval)
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1046, 'No database selected')
[SQL: DESCRIBE mg_app_settings]
(Background on this error at: http://sqlalche.me/e/2j85)

[需求] 通过api添加用户时应该把用户状态字段开放

需求] 通过api添加用户时应该把用户状态字段开放
批量导入用户时发现用户状态默认为禁用,通过修改status=0临时修改初始化状态,后来想一想也觉得不靠谱.用户状态的字段 api接口应该开放出来,让用户自行选择是正常还是禁用.

login failed ,how to resolve

2020-12-15 19:50 +08:00: [E 201215 19:50:58 web:1793] Uncaught exception POST /login/ (127.0.0.1)
2020-12-15 19:50 +08:00: HTTPServerRequest(protocol='http', host='mg.opendevops.cn', method='POST', uri='/login/', version='HTTP/1.0', remote_ip='127.0.0.1')
2020-12-15 19:50 +08:00: Traceback (most recent call last):
2020-12-15 19:50 +08:00: File "/usr/local/lib64/python3.6/site-packages/tornado/web.py", line 1702, in _execute
2020-12-15 19:50 +08:00: result = method(*self.path_args, **self.path_kwargs)
2020-12-15 19:50 +08:00: File "/opt/codo/codo-admin/mg/handlers/login_handler.py", line 138, in post
2020-12-15 19:50 +08:00: self.set_cookie('auth_key', auth_key, expires_days=1)
2020-12-15 19:50 +08:00: File "/usr/local/lib64/python3.6/site-packages/tornado/web.py", line 622, in set_cookie
2020-12-15 19:50 +08:00: value = escape.native_str(value)
2020-12-15 19:50 +08:00: File "/usr/local/lib64/python3.6/site-packages/tornado/escape.py", line 228, in to_unicode
2020-12-15 19:50 +08:00: raise TypeError("Expected bytes, unicode, or None; got %r" % type(value))
2020-12-15 19:50 +08:00: TypeError: Expected bytes, unicode, or None; got <class 'AttributeError'>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.