create_rbac_tables.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. #!/usr/bin/env python3
  2. """
  3. 创建RBAC权限管理相关数据库表
  4. """
  5. import pymysql
  6. from dotenv import load_dotenv
  7. import os
  8. load_dotenv()
  9. def get_db_connection():
  10. """获取数据库连接"""
  11. try:
  12. config = {
  13. 'host': os.getenv('DB_HOST', 'localhost'),
  14. 'port': int(os.getenv('DB_PORT', 3306)),
  15. 'user': os.getenv('DB_USER', 'root'),
  16. 'password': os.getenv('DB_PASSWORD', 'admin'),
  17. 'database': os.getenv('DB_NAME', 'lq_db'),
  18. 'charset': 'utf8mb4',
  19. 'autocommit': True
  20. }
  21. return pymysql.connect(**config)
  22. except Exception as e:
  23. print(f"数据库连接失败: {e}")
  24. return None
  25. def create_rbac_tables():
  26. """创建RBAC权限管理表"""
  27. print("🗄️ 创建RBAC权限管理表...")
  28. print("=" * 60)
  29. conn = get_db_connection()
  30. if not conn:
  31. print("❌ 数据库连接失败")
  32. return False
  33. cursor = conn.cursor()
  34. try:
  35. # 1. 菜单表 - 存储系统菜单结构
  36. print("📋 创建菜单表 (menus)...")
  37. cursor.execute("""
  38. CREATE TABLE IF NOT EXISTS menus (
  39. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  40. parent_id CHAR(36) NULL,
  41. name VARCHAR(100) NOT NULL COMMENT '菜单名称',
  42. title VARCHAR(100) NOT NULL COMMENT '菜单标题',
  43. path VARCHAR(200) NULL COMMENT '菜单路径',
  44. component VARCHAR(200) NULL COMMENT '组件路径',
  45. icon VARCHAR(50) NULL COMMENT '菜单图标',
  46. sort_order INT DEFAULT 0 COMMENT '排序顺序',
  47. menu_type ENUM('menu', 'button') DEFAULT 'menu' COMMENT '菜单类型',
  48. is_hidden BOOLEAN DEFAULT FALSE COMMENT '是否隐藏',
  49. is_active BOOLEAN DEFAULT TRUE COMMENT '是否启用',
  50. description TEXT NULL COMMENT '菜单描述',
  51. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  52. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  53. INDEX idx_parent_id (parent_id),
  54. INDEX idx_path (path),
  55. INDEX idx_sort_order (sort_order)
  56. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统菜单表'
  57. """)
  58. # 2. 角色表 - 存储用户角色
  59. print("👥 创建角色表 (roles)...")
  60. cursor.execute("""
  61. CREATE TABLE IF NOT EXISTS roles (
  62. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  63. name VARCHAR(50) NOT NULL UNIQUE COMMENT '角色名称',
  64. display_name VARCHAR(100) NOT NULL COMMENT '角色显示名称',
  65. description TEXT NULL COMMENT '角色描述',
  66. is_active BOOLEAN DEFAULT TRUE COMMENT '是否启用',
  67. is_system BOOLEAN DEFAULT FALSE COMMENT '是否系统角色',
  68. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  69. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  70. INDEX idx_name (name),
  71. INDEX idx_is_active (is_active)
  72. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表'
  73. """)
  74. # 3. 权限表 - 存储系统权限
  75. print("🔐 创建权限表 (permissions)...")
  76. cursor.execute("""
  77. CREATE TABLE IF NOT EXISTS permissions (
  78. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  79. name VARCHAR(100) NOT NULL UNIQUE COMMENT '权限名称',
  80. display_name VARCHAR(100) NOT NULL COMMENT '权限显示名称',
  81. resource VARCHAR(100) NOT NULL COMMENT '资源标识',
  82. action VARCHAR(50) NOT NULL COMMENT '操作类型',
  83. description TEXT NULL COMMENT '权限描述',
  84. is_active BOOLEAN DEFAULT TRUE COMMENT '是否启用',
  85. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  86. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  87. INDEX idx_name (name),
  88. INDEX idx_resource_action (resource, action),
  89. UNIQUE KEY uk_resource_action (resource, action)
  90. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表'
  91. """)
  92. # 4. 角色菜单关联表 - 角色可访问的菜单
  93. print("🔗 创建角色菜单关联表 (role_menus)...")
  94. cursor.execute("""
  95. CREATE TABLE IF NOT EXISTS role_menus (
  96. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  97. role_id CHAR(36) NOT NULL,
  98. menu_id CHAR(36) NOT NULL,
  99. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  100. UNIQUE KEY uk_role_menu (role_id, menu_id),
  101. INDEX idx_role_id (role_id),
  102. INDEX idx_menu_id (menu_id)
  103. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色菜单关联表'
  104. """)
  105. # 5. 角色权限关联表 - 角色拥有的权限
  106. print("🔗 创建角色权限关联表 (role_permissions)...")
  107. cursor.execute("""
  108. CREATE TABLE IF NOT EXISTS role_permissions (
  109. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  110. role_id CHAR(36) NOT NULL,
  111. permission_id CHAR(36) NOT NULL,
  112. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  113. UNIQUE KEY uk_role_permission (role_id, permission_id),
  114. INDEX idx_role_id (role_id),
  115. INDEX idx_permission_id (permission_id)
  116. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表'
  117. """)
  118. # 6. 用户角色关联表 - 用户拥有的角色
  119. print("🔗 创建用户角色关联表 (user_roles)...")
  120. cursor.execute("""
  121. CREATE TABLE IF NOT EXISTS user_roles (
  122. id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
  123. user_id CHAR(36) NOT NULL,
  124. role_id CHAR(36) NOT NULL,
  125. assigned_by CHAR(36) NULL COMMENT '分配者ID',
  126. assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  127. expires_at TIMESTAMP NULL COMMENT '过期时间',
  128. is_active BOOLEAN DEFAULT TRUE COMMENT '是否启用',
  129. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  130. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  131. UNIQUE KEY uk_user_role (user_id, role_id),
  132. INDEX idx_user_id (user_id),
  133. INDEX idx_role_id (role_id),
  134. INDEX idx_expires_at (expires_at)
  135. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表'
  136. """)
  137. print("✅ 所有RBAC表创建成功")
  138. # 插入初始数据
  139. print("\n📝 插入初始数据...")
  140. insert_initial_data(cursor)
  141. conn.commit()
  142. cursor.close()
  143. conn.close()
  144. print("\n" + "=" * 60)
  145. print("🎉 RBAC权限管理系统初始化完成!")
  146. print("=" * 60)
  147. return True
  148. except Exception as e:
  149. print(f"❌ 创建表失败: {e}")
  150. conn.rollback()
  151. cursor.close()
  152. conn.close()
  153. return False
  154. def insert_initial_data(cursor):
  155. """插入初始数据"""
  156. # 1. 插入系统菜单
  157. print(" 📋 插入系统菜单...")
  158. menus_data = [
  159. # 主菜单
  160. ('dashboard-menu', None, 'dashboard', '仪表盘', '/dashboard', 'dashboard/Index', 'House', 1, 'menu', False),
  161. ('profile-menu', None, 'profile', '个人资料', '/profile', 'user/Profile', 'User', 2, 'menu', False),
  162. ('admin-menu', None, 'admin', '系统管理', '/admin', None, 'Setting', 3, 'menu', False),
  163. # 系统管理子菜单
  164. ('admin-dashboard-menu', 'admin-menu', 'admin-dashboard', '管理概览', '/admin/dashboard', 'admin/Dashboard', 'Monitor', 1, 'menu', False),
  165. ('admin-users-menu', 'admin-menu', 'admin-users', '用户管理', '/admin/users', 'admin/Users', 'UserFilled', 2, 'menu', False),
  166. ('admin-roles-menu', 'admin-menu', 'admin-roles', '角色管理', '/admin/roles', 'admin/Roles', 'Avatar', 3, 'menu', False),
  167. ('admin-menus-menu', 'admin-menu', 'admin-menus', '菜单管理', '/admin/menus', 'admin/Menus', 'Menu', 4, 'menu', False),
  168. ('admin-permissions-menu', 'admin-menu', 'admin-permissions', '权限管理', '/admin/permissions', 'admin/Permissions', 'Key', 5, 'menu', False),
  169. ('admin-apps-menu', 'admin-menu', 'admin-apps', '应用管理', '/admin/apps', 'admin/Apps', 'Grid', 6, 'menu', False),
  170. ('admin-logs-menu', 'admin-menu', 'admin-logs', '系统日志', '/admin/logs', 'admin/Logs', 'Document', 7, 'menu', False),
  171. ('admin-settings-menu', 'admin-menu', 'admin-settings', '系统设置', '/admin/settings', 'admin/Settings', 'Tools', 8, 'menu', False),
  172. # 应用管理按钮权限
  173. ('apps-create-btn', 'admin-apps-menu', 'apps-create', '创建应用', None, None, 'Plus', 1, 'button', False),
  174. ('apps-edit-btn', 'admin-apps-menu', 'apps-edit', '编辑应用', None, None, 'Edit', 2, 'button', False),
  175. ('apps-delete-btn', 'admin-apps-menu', 'apps-delete', '删除应用', None, None, 'Delete', 3, 'button', False),
  176. ('apps-secret-btn', 'admin-apps-menu', 'apps-secret', '查看密钥', None, None, 'Key', 4, 'button', False),
  177. ]
  178. # 先插入父菜单,再插入子菜单
  179. menu_id_map = {}
  180. for menu_data in menus_data:
  181. name, parent_name, key, title, path, component, icon, sort_order, menu_type, is_hidden = menu_data
  182. parent_id = menu_id_map.get(parent_name) if parent_name else None
  183. cursor.execute("""
  184. INSERT INTO menus (id, parent_id, name, title, path, component, icon, sort_order, menu_type, is_hidden)
  185. VALUES (UUID(), %s, %s, %s, %s, %s, %s, %s, %s, %s)
  186. """, (parent_id, key, title, path, component, icon, sort_order, menu_type, is_hidden))
  187. # 获取插入的菜单ID
  188. cursor.execute("SELECT id FROM menus WHERE name = %s ORDER BY created_at DESC LIMIT 1", (key,))
  189. menu_id = cursor.fetchone()[0]
  190. menu_id_map[name] = menu_id
  191. # 2. 插入系统角色
  192. print(" 👥 插入系统角色...")
  193. roles_data = [
  194. ('super_admin', '超级管理员', '拥有系统所有权限的超级管理员', True, True),
  195. ('admin', '管理员', '拥有大部分管理权限的管理员', True, True),
  196. ('user_manager', '用户管理员', '负责用户管理的管理员', True, False),
  197. ('app_manager', '应用管理员', '负责应用管理的管理员', True, False),
  198. ('user', '普通用户', '系统普通用户', True, True),
  199. ]
  200. role_id_map = {}
  201. for role_data in roles_data:
  202. name, display_name, description, is_active, is_system = role_data
  203. cursor.execute("""
  204. INSERT INTO roles (id, name, display_name, description, is_active, is_system)
  205. VALUES (UUID(), %s, %s, %s, %s, %s)
  206. """, (name, display_name, description, is_active, is_system))
  207. # 获取插入的角色ID
  208. cursor.execute("SELECT id FROM roles WHERE name = %s", (name,))
  209. role_id = cursor.fetchone()[0]
  210. role_id_map[name] = role_id
  211. # 3. 插入系统权限
  212. print(" 🔐 插入系统权限...")
  213. permissions_data = [
  214. # 用户管理权限
  215. ('user.view', '查看用户', 'user', 'view', '查看用户列表和详情'),
  216. ('user.create', '创建用户', 'user', 'create', '创建新用户'),
  217. ('user.edit', '编辑用户', 'user', 'edit', '编辑用户信息'),
  218. ('user.delete', '删除用户', 'user', 'delete', '删除用户'),
  219. ('user.assign_role', '分配角色', 'user', 'assign_role', '为用户分配角色'),
  220. # 角色管理权限
  221. ('role.view', '查看角色', 'role', 'view', '查看角色列表和详情'),
  222. ('role.create', '创建角色', 'role', 'create', '创建新角色'),
  223. ('role.edit', '编辑角色', 'role', 'edit', '编辑角色信息'),
  224. ('role.delete', '删除角色', 'role', 'delete', '删除角色'),
  225. ('role.assign_permission', '分配权限', 'role', 'assign_permission', '为角色分配权限'),
  226. # 菜单管理权限
  227. ('menu.view', '查看菜单', 'menu', 'view', '查看菜单列表和详情'),
  228. ('menu.create', '创建菜单', 'menu', 'create', '创建新菜单'),
  229. ('menu.edit', '编辑菜单', 'menu', 'edit', '编辑菜单信息'),
  230. ('menu.delete', '删除菜单', 'menu', 'delete', '删除菜单'),
  231. # 应用管理权限
  232. ('app.view', '查看应用', 'app', 'view', '查看应用列表和详情'),
  233. ('app.create', '创建应用', 'app', 'create', '创建新应用'),
  234. ('app.edit', '编辑应用', 'app', 'edit', '编辑应用信息'),
  235. ('app.delete', '删除应用', 'app', 'delete', '删除应用'),
  236. ('app.secret', '查看密钥', 'app', 'secret', '查看应用密钥'),
  237. # 系统管理权限
  238. ('system.view', '查看系统', 'system', 'view', '查看系统信息'),
  239. ('system.config', '系统配置', 'system', 'config', '修改系统配置'),
  240. ('system.log', '查看日志', 'system', 'log', '查看系统日志'),
  241. ]
  242. permission_id_map = {}
  243. for perm_data in permissions_data:
  244. name, display_name, resource, action, description = perm_data
  245. cursor.execute("""
  246. INSERT INTO permissions (id, name, display_name, resource, action, description)
  247. VALUES (UUID(), %s, %s, %s, %s, %s)
  248. """, (name, display_name, resource, action, description))
  249. # 获取插入的权限ID
  250. cursor.execute("SELECT id FROM permissions WHERE name = %s", (name,))
  251. permission_id = cursor.fetchone()[0]
  252. permission_id_map[name] = permission_id
  253. # 4. 分配角色菜单权限
  254. print(" 🔗 分配角色菜单权限...")
  255. # 超级管理员 - 所有菜单
  256. super_admin_id = role_id_map['super_admin']
  257. cursor.execute("SELECT id FROM menus")
  258. all_menu_ids = [row[0] for row in cursor.fetchall()]
  259. for menu_id in all_menu_ids:
  260. cursor.execute("""
  261. INSERT INTO role_menus (id, role_id, menu_id)
  262. VALUES (UUID(), %s, %s)
  263. """, (super_admin_id, menu_id))
  264. # 管理员 - 除了系统设置外的所有菜单
  265. admin_id = role_id_map['admin']
  266. cursor.execute("SELECT id FROM menus WHERE name != 'admin-settings'")
  267. admin_menu_ids = [row[0] for row in cursor.fetchall()]
  268. for menu_id in admin_menu_ids:
  269. cursor.execute("""
  270. INSERT INTO role_menus (id, role_id, menu_id)
  271. VALUES (UUID(), %s, %s)
  272. """, (admin_id, menu_id))
  273. # 普通用户 - 基础菜单
  274. user_id = role_id_map['user']
  275. basic_menus = ['dashboard', 'profile', 'apps']
  276. cursor.execute("SELECT id FROM menus WHERE name IN %s", (basic_menus,))
  277. user_menu_ids = [row[0] for row in cursor.fetchall()]
  278. for menu_id in user_menu_ids:
  279. cursor.execute("""
  280. INSERT INTO role_menus (id, role_id, menu_id)
  281. VALUES (UUID(), %s, %s)
  282. """, (user_id, menu_id))
  283. # 5. 分配角色权限
  284. print(" 🔗 分配角色权限...")
  285. # 超级管理员 - 所有权限
  286. for permission_id in permission_id_map.values():
  287. cursor.execute("""
  288. INSERT INTO role_permissions (id, role_id, permission_id)
  289. VALUES (UUID(), %s, %s)
  290. """, (super_admin_id, permission_id))
  291. # 管理员 - 除了系统配置外的权限
  292. admin_permissions = [p for p in permission_id_map.keys() if not p.startswith('system.config')]
  293. for perm_name in admin_permissions:
  294. cursor.execute("""
  295. INSERT INTO role_permissions (id, role_id, permission_id)
  296. VALUES (UUID(), %s, %s)
  297. """, (admin_id, permission_id_map[perm_name]))
  298. # 普通用户 - 基础权限
  299. user_permissions = ['app.view', 'app.create', 'app.edit', 'app.secret']
  300. for perm_name in user_permissions:
  301. cursor.execute("""
  302. INSERT INTO role_permissions (id, role_id, permission_id)
  303. VALUES (UUID(), %s, %s)
  304. """, (user_id, permission_id_map[perm_name]))
  305. # 6. 为现有admin用户分配超级管理员角色
  306. print(" 👤 为admin用户分配超级管理员角色...")
  307. cursor.execute("SELECT id FROM users WHERE username = 'admin'")
  308. admin_user = cursor.fetchone()
  309. if admin_user:
  310. admin_user_id = admin_user[0]
  311. cursor.execute("""
  312. INSERT INTO user_roles (id, user_id, role_id, assigned_by)
  313. VALUES (UUID(), %s, %s, %s)
  314. """, (admin_user_id, super_admin_id, admin_user_id))
  315. print(" ✅ admin用户已分配超级管理员角色")
  316. else:
  317. print(" ⚠️ 未找到admin用户")
  318. print(" ✅ 初始数据插入完成")
  319. if __name__ == "__main__":
  320. create_rbac_tables()