1、问题描述
Flask-Admin插件作项目的后台管理,有一个用户表、角色表、用户角色关联表等,用户表中要限制管理员删除自己,所以在数据库(使用的是postgresql)中的用户表上加了一个触发器做限制。
触发器函数
在删除用户之前先去用户角色关联表中差这个用户是不是拥有管理员角色,如果有就不允许删除
CREATE or Replace FUNCTION del_admin() RETURNS trigger AS $del_admin$
BEGIN
If (TG_OP = 'DELETE') THEN
If EXISTS(SELECT * FROM userroles WHERE user_id=OLD.id AND role_id='1') Then
raise notice '不允许删除管理员: %, id:%', OLD.username, OLD.id;
return null;
ELSE
return OLD;
END IF;
END IF;
END;
$del_admin$ LANGUAGE plpgsql;
在shell
中使用sql
语句删除拥有管理员角色的用户时,触发器起作用,但是在后台管理界面删除管理员是能成功删除的,我的第一感觉是不是Flask-Admin绕过了触发器(怎么可能!)
2、解决过程
将后台在删除用户时orm语句转化后的sql语句全部打印出来分析:
2017-07-26 19:15:57,381 INFO sqlalchemy.engine.base.Engine {'param_1': 15}
2017-07-26 19:15:57,385 INFO sqlalchemy.engine.base.Engine DELETE FROM userroles WHERE userroles.user_id = %(user_id)s AND userroles.role_id = %(role_id)s
2017-07-26 19:15:57,385 INFO sqlalchemy.engine.base.Engine ({'user_id': 15, 'role_id': 1}, {'user_id': 15, 'role_id': 4})
2017-07-26 19:15:57,390 INFO sqlalchemy.engine.base.Engine DELETE FROM users WHERE users.id = %(id)s
2017-07-26 19:15:57,390 INFO sqlalchemy.engine.base.Engine {'id': 15}
2017-07-26 19:15:57,394 INFO sqlalchemy.engine.base.Engine COMMIT
从上面打印出来的信息可以看出,后台在删除用户时先将该用户所拥有的角色先从用户角色关联表中删除,最后再删除用户。
你都先把用户角色关联表中该用户所有的角色删除了,触发器当然拦不住了。
所以如果谁使用Flask-admin做后台同时也有这样的需求,最好先看看执行删除之前sql是什么样的,再决定将触发器设置在那个表上。
网友评论