Skip to content

Commit

Permalink
name转id的第一版,初步测试查询权限功能可用。
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoQuote committed Mar 20, 2019
1 parent e5120b4 commit a022b92
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 48 deletions.
28 changes: 17 additions & 11 deletions common/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ def setUpClass(cls):
cls.superuser1 = User(username='super1', is_superuser=True)
cls.superuser1.save()
cls.now = datetime.datetime.now()
cls.slave1 = Instance(instance_name='test_slave_instance', type='slave', db_type='mysql',
host='testhost', port=3306, user='mysql_user', password='mysql_password')
cls.slave1.save()
# 批量创建数据 ddl ,u1 ,g1, yesterday 组, 2 个数据
ddl_workflow = [SqlWorkflow(
workflow_name='ddl %s' % i,
Expand All @@ -346,8 +349,9 @@ def setUpClass(cls):
engineer_display=cls.u1.display,
audit_auth_groups='some_group',
create_time=cls.now - datetime.timedelta(days=1),
status = '已正常结束',
is_backup = '是',
status='workflow_finish',
is_backup='是',
instance=cls.slave1,
instance_name='some_instance',
db_name='some_db',
sql_content='some_sql',
Expand All @@ -362,8 +366,9 @@ def setUpClass(cls):
engineer_display=cls.u2.display,
audit_auth_groups='some_group',
create_time=cls.now - datetime.timedelta(days=2),
status='已正常结束',
status='workflow_finish',
is_backup='是',
instance=cls.slave1,
instance_name='some_instance',
db_name='some_db',
sql_content='some_sql',
Expand All @@ -375,6 +380,15 @@ def setUpClass(cls):
#
#) for i in range(20)]

@classmethod
def tearDownClass(cls):
SqlWorkflow.objects.all().delete()
QueryLog.objects.all().delete()
cls.u1.delete()
cls.u2.delete()
cls.superuser1.delete()
cls.slave1.delete()

def testGetDateList(self):
dao = ChartDao()
end = datetime.date.today()
Expand Down Expand Up @@ -420,14 +434,6 @@ def testDashboard(self):
r = c.get('/dashboard/')
self.assertEqual(r.status_code, 200)

@classmethod
def tearDownClass(cls):
SqlWorkflow.objects.all().delete()
QueryLog.objects.all().delete()
cls.u1.delete()
cls.u2.delete()
cls.superuser1.delete()


class AuthTest(TestCase):

Expand Down
3 changes: 2 additions & 1 deletion sql/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class QueryLogAdmin(admin.ModelAdmin):
@admin.register(QueryPrivileges)
class QueryPrivilegesAdmin(admin.ModelAdmin):
list_display = (
'user_display', 'instance_name', 'db_name', 'table_name', 'valid_date', 'limit_num', 'create_time')
# TODO 删除instance_name
'user_display', 'instance_name', 'instance', 'db_name', 'table_name', 'valid_date', 'limit_num', 'create_time')
search_fields = ['user_display', 'instance_name']
list_filter = ('user_display', 'instance_name', 'db_name', 'table_name',)

Expand Down
6 changes: 5 additions & 1 deletion sql/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class SqlWorkflow(models.Model):
status = models.CharField(max_length=50, choices=SQL_WORKFLOW_CHOICES)
is_backup = models.CharField('是否备份', choices=(('否', '否'), ('是', '是')), max_length=20)
review_content = models.TextField('自动审核内容的JSON格式')
# TODO 需要删除instance_name 字段
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
instance_name = models.CharField('实例名称', max_length=50)
db_name = models.CharField('数据库', max_length=60)
Expand Down Expand Up @@ -244,6 +245,8 @@ class QueryPrivilegesApply(models.Model):
title = models.CharField('申请标题', max_length=50)
user_name = models.CharField('申请人', max_length=30)
user_display = models.CharField('申请人中文名', max_length=50, default='')
# TODO 后期删除 instance_name
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
instance_name = models.CharField('实例名称', max_length=50)
db_list = models.TextField('数据库') # 逗号分隔的数据库列表
table_list = models.TextField('表') # 逗号分隔的表列表
Expand All @@ -270,6 +273,7 @@ class QueryPrivileges(models.Model):
privilege_id = models.AutoField(primary_key=True)
user_name = models.CharField('用户名', max_length=30)
user_display = models.CharField('申请人中文名', max_length=50, default='')
# TODO 后期删除instance_name
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
instance_name = models.CharField('实例名称', max_length=50)
db_name = models.CharField('数据库', max_length=200)
Expand All @@ -293,7 +297,6 @@ class Meta:

# 记录在线查询sql的日志
class QueryLog(models.Model):
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
instance_name = models.CharField('实例名称', max_length=50)
db_name = models.CharField('数据库名称', max_length=30)
sqllog = models.TextField('执行的sql查询')
Expand All @@ -320,6 +323,7 @@ class DataMaskingColumns(models.Model):
rule_type = models.IntegerField('规则类型',
choices=((1, '手机号'), (2, '证件号码'), (3, '银行卡'), (4, '邮箱'), (5, '金额'), (6, '其他')))
active = models.IntegerField('激活状态', choices=((0, '未激活'), (1, '激活')))
# TODO 暂时设置为允许为空, 迁移完成后再修改
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
instance_name = models.CharField('实例名称', max_length=50)
table_schema = models.CharField('字段所在库名', max_length=64)
Expand Down
62 changes: 33 additions & 29 deletions sql/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def query_audit_call_back(workflow_id, workflow_status):
insertlist = [QueryPrivileges(
user_name=apply_queryset.user_name,
user_display=apply_queryset.user_display,
instance = apply_queryset.instance,
instance_name=apply_queryset.instance_name, db_name=db_name,
table_name=apply_queryset.table_list, valid_date=apply_queryset.valid_date,
limit_num=apply_queryset.limit_num, priv_type=apply_queryset.priv_type) for db_name in
Expand All @@ -54,6 +55,7 @@ def query_audit_call_back(workflow_id, workflow_status):
insertlist = [QueryPrivileges(
user_name=apply_queryset.user_name,
user_display=apply_queryset.user_display,
instance=apply_queryset.instance,
instance_name=apply_queryset.instance_name, db_name=apply_queryset.db_list,
table_name=table_name, valid_date=apply_queryset.valid_date,
limit_num=apply_queryset.limit_num, priv_type=apply_queryset.priv_type) for table_name in
Expand All @@ -77,12 +79,12 @@ def query_priv_check(user, instance_name, db_name, sql_content, limit_num):
elif re.match(r"^show\s+create\s+table", sql_content.lower()):
tb_name = re.sub('^show\s+create\s+table', '', sql_content, count=1, flags=0).strip()
# 先判断是否有整库权限
db_privileges = QueryPrivileges.objects.filter(user_name=user.username, instance_name=instance_name,
db_privileges = QueryPrivileges.objects.filter(user_name=user.username, instance= instance,
db_name=db_name, priv_type=1,
valid_date__gte=datetime.datetime.now(), is_deleted=0)
# 无整库权限再验证表权限
if len(db_privileges) == 0:
tb_privileges = QueryPrivileges.objects.filter(user_name=user.username, instance_name=instance_name,
tb_privileges = QueryPrivileges.objects.filter(user_name=user.username, instance=instance,
db_name=db_name, table_name=tb_name, priv_type=2,
valid_date__gte=datetime.datetime.now(), is_deleted=0)
if len(tb_privileges) == 0:
Expand All @@ -98,7 +100,7 @@ def query_priv_check(user, instance_name, db_name, sql_content, limit_num):
if table_ref_result['status'] == 0:
table_ref = table_ref_result['data']
# 获取表信息,校验是否拥有全部表查询权限
QueryPrivilegesOb = QueryPrivileges.objects.filter(user_name=user.username, instance_name=instance_name)
QueryPrivilegesOb = QueryPrivileges.objects.filter(user_name=user.username, instance=instance)
# 先判断是否有整库权限
for table in table_ref:
db_privileges = QueryPrivilegesOb.filter(db_name=table['db'], priv_type=1,
Expand All @@ -116,7 +118,7 @@ def query_priv_check(user, instance_name, db_name, sql_content, limit_num):
# 获取表数据报错,检查配置文件是否允许继续执行,并进行库权限校验
else:
# 校验库权限,防止inception的语法树打印错误时连库权限也未做校验
privileges = QueryPrivileges.objects.filter(user_name=user.username, instance_name=instance_name,
privileges = QueryPrivileges.objects.filter(user_name=user.username, instance=instance,
db_name=db_name,
valid_date__gte=datetime.datetime.now(),
is_deleted=0)
Expand All @@ -134,22 +136,22 @@ def query_priv_check(user, instance_name, db_name, sql_content, limit_num):
db_list = [table_info['db'] for table_info in table_ref]
table_list = [table_info['table'] for table_info in table_ref]
user_limit_num = QueryPrivileges.objects.filter(user_name=user.username,
instance_name=instance_name,
instance=instance,
db_name__in=db_list,
table_name__in=table_list,
valid_date__gte=datetime.datetime.now(),
is_deleted=0).aggregate(Min('limit_num'))['limit_num__min']
if user_limit_num is None:
# 如果表没获取到则获取涉及库的最小limit限制
user_limit_num = QueryPrivileges.objects.filter(user_name=user.username,
instance_name=instance_name,
instance=instance,
db_name=db_name,
valid_date__gte=datetime.datetime.now(), is_deleted=0
).aggregate(Min('limit_num'))['limit_num__min']
else:
# 如果表没获取到则获取涉及库的最小limit限制
user_limit_num = QueryPrivileges.objects.filter(user_name=user.username,
instance_name=instance_name,
instance=instance,
db_name=db_name,
valid_date__gte=datetime.datetime.now(),
is_deleted=0).aggregate(Min('limit_num'))['limit_num__min']
Expand Down Expand Up @@ -239,10 +241,11 @@ def applyforprivileges(request):

# 判断是否需要限制到表级别的权限
# 库权限
ins = Instance.objects.get(instance_name=instance_name)
if int(priv_type) == 1:
db_list = db_list.split(',')
# 检查申请账号是否已拥整个库的查询权限
own_dbs = QueryPrivileges.objects.filter(instance_name=instance_name, user_name=user.username,
own_dbs = QueryPrivileges.objects.filter(instance=ins, user_name=user.username,
db_name__in=db_list,
valid_date__gte=datetime.datetime.now(), priv_type=1,
is_deleted=0).values('db_name')
Expand All @@ -259,7 +262,7 @@ def applyforprivileges(request):
elif int(priv_type) == 2:
table_list = table_list.split(',')
# 检查申请账号是否已拥有该表的查询权限
own_tables = QueryPrivileges.objects.filter(instance_name=instance_name, user_name=user.username,
own_tables = QueryPrivileges.objects.filter(instance=ins, user_name=user.username,
db_name=db_name,
table_name__in=table_list, valid_date__gte=datetime.datetime.now(),
priv_type=2, is_deleted=0).values('table_name')
Expand All @@ -277,25 +280,26 @@ def applyforprivileges(request):
try:
with transaction.atomic():
# 保存申请信息到数据库
applyinfo = QueryPrivilegesApply()
applyinfo.title = title
applyinfo.group_id = group_id
applyinfo.group_name = group_name
applyinfo.audit_auth_groups = Audit.settings(group_id, WorkflowDict.workflow_type['query'])
applyinfo.user_name = user.username
applyinfo.user_display = user.display
applyinfo.instance_name = instance_name
applyinfo = QueryPrivilegesApply(
title=title,
group_id=group_id,
group_name=group_name,
audit_auth_groups=Audit.settings(group_id, WorkflowDict.workflow_type['query']),
user_name=user.username,
user_display=user.display,
instance=ins,
instance_name=instance_name,
priv_type=int(priv_type),
valid_date=valid_date,
status=WorkflowDict.workflow_status['audit_wait'],
limit_num=limit_num
)
if int(priv_type) == 1:
applyinfo.db_list = ','.join(db_list)
applyinfo.table_list = ''
elif int(priv_type) == 2:
applyinfo.db_list = db_name
applyinfo.table_list = ','.join(table_list)
applyinfo.priv_type = int(priv_type)
applyinfo.valid_date = valid_date
applyinfo.status = WorkflowDict.workflow_status['audit_wait'] # 待审核
applyinfo.limit_num = limit_num
applyinfo.create_user = user.username
applyinfo.save()
apply_id = applyinfo.apply_id

Expand Down Expand Up @@ -331,14 +335,14 @@ def getuserprivileges(request):
# 获取用户的权限数据
if user.is_superuser:
if user_name != 'all':
privileges_list_obj = QueryPrivileges.objects.all().filter(user_name=user_name,
is_deleted=0,
table_name__contains=search,
valid_date__gte=datetime.datetime.now())
privileges_list_obj = QueryPrivileges.objects.filter(user_name=user_name,
is_deleted=0,
table_name__contains=search,
valid_date__gte=datetime.datetime.now())
else:
privileges_list_obj = QueryPrivileges.objects.all().filter(is_deleted=0,
table_name__contains=search,
valid_date__gte=datetime.datetime.now())
privileges_list_obj = QueryPrivileges.objects.filter(is_deleted=0,
table_name__contains=search,
valid_date__gte=datetime.datetime.now())
else:
privileges_list_obj = QueryPrivileges.objects.filter(user_name=user.username,
table_name__contains=search,
Expand Down
Loading

0 comments on commit a022b92

Please sign in to comment.