auth.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import json
  2. from datetime import datetime, timedelta
  3. from typing import Optional, List
  4. from fastapi import APIRouter, Depends, HTTPException, status, Request
  5. from pydantic import BaseModel, ConfigDict, Field
  6. from pydantic.alias_generators import to_camel
  7. from sqlalchemy.orm import Session
  8. from app.database import get_db
  9. from app.models.system import SysUser, SysTenant, SysUserRole, SysRole, SysRoleMenu, SysMenu
  10. from app.schemas import R
  11. from app.utils.security import verify_password, hash_password
  12. from app.utils import next_id
  13. from app.middleware import create_access_token, get_current_user
  14. from app.utils.redis_client import get_redis
  15. router = APIRouter()
  16. class LoginBody(BaseModel):
  17. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  18. tenant_id: str = "000000"
  19. username: str
  20. password: str
  21. client_id: str = "e5cd7e4891bf95d1d19206ce24a7b32e"
  22. grant_type: str = "password"
  23. class LoginVo(BaseModel):
  24. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  25. access_token: str
  26. refresh_token: str = ""
  27. expire_in: int
  28. refresh_expire_in: int = 0
  29. client_id: str = ""
  30. scope: str = ""
  31. openid: str = ""
  32. @router.post("/login")
  33. def login(body: LoginBody, db: Session = Depends(get_db)):
  34. user = (
  35. db.query(SysUser)
  36. .filter(
  37. SysUser.user_name == body.username,
  38. SysUser.del_flag == "0",
  39. )
  40. .first()
  41. )
  42. if not user:
  43. return R.fail("用户不存在或密码错误")
  44. if not verify_password(body.password, user.password):
  45. return R.fail("用户不存在或密码错误")
  46. if user.status != "0":
  47. return R.fail("用户已被停用")
  48. tenant_id = body.tenant_id or "000000"
  49. permissions = _get_user_permissions(db, user.user_id, tenant_id)
  50. roles = _get_user_roles(db, user.user_id, tenant_id)
  51. token_data = {
  52. "login_id": str(user.user_id),
  53. "tenant_id": tenant_id,
  54. "user_id": user.user_id,
  55. "user_name": user.user_name,
  56. "nick_name": user.nick_name,
  57. "dept_id": user.dept_id,
  58. }
  59. expire_minutes = 1440
  60. access_token = create_access_token(
  61. token_data,
  62. timedelta(minutes=expire_minutes),
  63. )
  64. refresh_token = create_access_token(
  65. token_data,
  66. timedelta(minutes=expire_minutes * 2),
  67. )
  68. redis = get_redis()
  69. session_key = f"login:session:{user.user_id}:{tenant_id}"
  70. session_data = {
  71. "user_id": user.user_id,
  72. "user_name": user.user_name,
  73. "nick_name": user.nick_name,
  74. "dept_id": user.dept_id or 0,
  75. "tenant_id": tenant_id,
  76. "permissions": list(permissions),
  77. "roles": list(roles),
  78. }
  79. redis.setex(session_key, expire_minutes * 60, json.dumps(session_data, ensure_ascii=False))
  80. user.login_ip = "127.0.0.1"
  81. user.login_date = datetime.now()
  82. db.commit()
  83. return R.ok(
  84. data={
  85. "access_token": access_token,
  86. "refresh_token": refresh_token,
  87. "expire_in": expire_minutes * 60,
  88. "refresh_expire_in": 0,
  89. "client_id": body.client_id or "",
  90. "scope": "",
  91. "openid": "",
  92. }
  93. )
  94. @router.post("/logout")
  95. def logout(current_user: dict = Depends(get_current_user)):
  96. user_id = current_user.get("user_id")
  97. tenant_id = current_user.get("tenant_id", "000000")
  98. redis = get_redis()
  99. session_key = f"login:session:{user_id}:{tenant_id}"
  100. redis.delete(session_key)
  101. return R.ok(msg="退出成功")
  102. @router.get("/tenant/list")
  103. def tenant_list(db: Session = Depends(get_db)):
  104. tenants = db.query(SysTenant).filter(SysTenant.status == "0", SysTenant.del_flag == "0").all()
  105. return R.ok(data=[
  106. {
  107. "tenantId": t.tenant_id,
  108. "companyName": t.company_name,
  109. "domain": t.domain,
  110. }
  111. for t in tenants
  112. ])
  113. def _get_user_permissions(db: Session, user_id: int, tenant_id: str) -> set:
  114. role_ids = [r.role_id for r in db.query(SysUserRole).filter(SysUserRole.user_id == user_id).all()]
  115. if not role_ids:
  116. return set()
  117. menu_ids = [m.menu_id for m in db.query(SysRoleMenu).filter(SysRoleMenu.role_id.in_(role_ids)).all()]
  118. if not menu_ids:
  119. return set()
  120. menus = db.query(SysMenu).filter(SysMenu.menu_id.in_(menu_ids), SysMenu.status == "0").all()
  121. return {m.perms for m in menus if m.perms}
  122. def _get_user_roles(db: Session, user_id: int, tenant_id: str) -> set:
  123. role_ids = [r.role_id for r in db.query(SysUserRole).filter(SysUserRole.user_id == user_id).all()]
  124. if not role_ids:
  125. return set()
  126. roles = db.query(SysRole).filter(SysRole.role_id.in_(role_ids), SysRole.del_flag == "0").all()
  127. return {r.role_key for r in roles}