feat: user admin cache
This commit is contained in:
parent
0f20fad339
commit
22014a7b0e
@ -76,7 +76,10 @@ var sa = {
|
||||
return layer.alert('失败:' + res.msg);
|
||||
},
|
||||
success403: function(res){ // code=403, 代表权限不足
|
||||
return layer.alert("权限不足," + res.msg, {icon: 5});
|
||||
return layer.alert("权限不足," + res.msg, {icon: 5}, function () {
|
||||
layer.closeAll();
|
||||
return sa.$page.openLogin(cfg.login_url);
|
||||
});
|
||||
},
|
||||
success401: function(res){ // code=401, 代表未登录
|
||||
return layer.confirm("您当前暂未登录,是否立即登录?", {}, function(){
|
||||
@ -88,6 +91,9 @@ var sa = {
|
||||
if(xhr.status == 0){
|
||||
return layer.alert('无法连接到服务器,请检查网络');
|
||||
}
|
||||
if (xhr.status == 403) {
|
||||
return cfg.success403({msg: '请尝试重新登录'});
|
||||
}
|
||||
return layer.alert("异常:" + JSON.stringify(xhr));
|
||||
},
|
||||
complete: function(xhr, ts) { // 成功失败都会执行
|
||||
|
@ -1,3 +1,4 @@
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from fastapi_amis_admin.crud import BaseApiOut
|
||||
@ -123,5 +124,9 @@ class UserRoutes(Plugin):
|
||||
token_info.roles = ",".join(
|
||||
await self.user_role_services.get_user_roles(user.username)
|
||||
)
|
||||
response.set_cookie("Authorization", f"bearer {token_info.access_token}")
|
||||
response.set_cookie(
|
||||
"Authorization",
|
||||
f"bearer {token_info.access_token}",
|
||||
expires=datetime.datetime.now(datetime.UTC) + datetime.timedelta(days=3),
|
||||
)
|
||||
return BaseApiOut(code=0, data=token_info)
|
||||
|
@ -18,7 +18,9 @@ class UserUpdateRoutes(Plugin):
|
||||
_prefix = "/user"
|
||||
|
||||
def __init__(
|
||||
self, user_services: UserServices, user_role_services: UserRoleServices
|
||||
self,
|
||||
user_services: UserServices,
|
||||
user_role_services: UserRoleServices,
|
||||
):
|
||||
self.user_services = user_services
|
||||
self.user_role_services = user_role_services
|
||||
@ -69,7 +71,12 @@ class UserUpdateRoutes(Plugin):
|
||||
|
||||
@handler.get("/avatar/{uid}/{file_path}", student=True, out=True)
|
||||
async def get_avatar(self, request: Request, uid: int, file_path: str):
|
||||
if request.user.id != uid:
|
||||
can_see = False
|
||||
if await self.user_role_services.is_admin(request.user.username):
|
||||
can_see = True
|
||||
if request.user.id == uid:
|
||||
can_see = True
|
||||
if not can_see:
|
||||
return BaseApiOut(status=500, msg="无权查看他人头像")
|
||||
path = await get_avatar(uid, file_path)
|
||||
if not path:
|
||||
|
26
src/services/users/cache.py
Normal file
26
src/services/users/cache.py
Normal file
@ -0,0 +1,26 @@
|
||||
from typing import List
|
||||
|
||||
from persica.factory.component import AsyncInitializingComponent
|
||||
|
||||
from src.core.redis_db import RedisDB
|
||||
|
||||
|
||||
class UserAdminCache(AsyncInitializingComponent):
|
||||
def __init__(self, redis: RedisDB):
|
||||
self.client = redis.client
|
||||
self.qname = "users:admin"
|
||||
|
||||
async def ismember(self, username: str) -> bool:
|
||||
return await self.client.sismember(self.qname, username)
|
||||
|
||||
async def get_all(self) -> List[str]:
|
||||
return [str_data for str_data in await self.client.smembers(self.qname)]
|
||||
|
||||
async def set(self, username: str) -> bool:
|
||||
return await self.client.sadd(self.qname, username)
|
||||
|
||||
async def remove(self, username: str) -> bool:
|
||||
return await self.client.srem(self.qname, username)
|
||||
|
||||
async def remove_all(self) -> bool:
|
||||
return await self.client.delete(self.qname)
|
@ -1,4 +1,4 @@
|
||||
from typing import Optional
|
||||
from typing import Optional, List, Sequence
|
||||
|
||||
from fastapi_user_auth.auth import Auth
|
||||
from fastapi_user_auth.auth.backends.redis import RedisTokenStore
|
||||
@ -101,7 +101,7 @@ class UserRepo(AsyncInitializingComponent):
|
||||
ptype: Optional[str] = None,
|
||||
v0: Optional[str] = None,
|
||||
v1: Optional[str] = None,
|
||||
) -> Optional[RoleModel]:
|
||||
) -> Sequence[CasbinRule]:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
statement = select(self.rule_model)
|
||||
if ptype:
|
||||
@ -111,7 +111,7 @@ class UserRepo(AsyncInitializingComponent):
|
||||
if v1:
|
||||
statement = statement.where(self.rule_model.v1 == v1)
|
||||
r = await session.exec(statement)
|
||||
return r.first()
|
||||
return r.all()
|
||||
|
||||
async def create_role_rule(self, rule: "CasbinRule") -> CasbinRule:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
|
@ -5,6 +5,7 @@ from fastapi_user_auth.utils.casbin import update_subject_roles
|
||||
from persica.factory.component import AsyncInitializingComponent
|
||||
from pydantic import SecretStr
|
||||
|
||||
from .cache import UserAdminCache
|
||||
from .models import UserModel, RoleModel
|
||||
from src.services.users.repositories import UserRepo
|
||||
from .schemas import UserRoleEnum
|
||||
@ -99,8 +100,9 @@ class UserServices(AsyncInitializingComponent):
|
||||
class UserRoleServices(AsyncInitializingComponent):
|
||||
__order__ = 1
|
||||
|
||||
def __init__(self, repo: UserRepo):
|
||||
def __init__(self, repo: UserRepo, cache: UserAdminCache):
|
||||
self.repo = repo
|
||||
self.cache = cache
|
||||
self.role_model = RoleModel
|
||||
self.rule_model = CasbinRule
|
||||
|
||||
@ -112,6 +114,15 @@ class UserRoleServices(AsyncInitializingComponent):
|
||||
if await self.get_role(key=key) is None:
|
||||
await self.create_role(key, f"{key} role")
|
||||
print(f"Create role: {key}")
|
||||
await self.cache.remove_all()
|
||||
for admin in await self.get_role_rule("g", None, "r:admin"):
|
||||
await self.cache.set(admin.v0[2:])
|
||||
|
||||
async def is_admin(self, username: str) -> bool:
|
||||
return await self.cache.ismember(username)
|
||||
|
||||
async def get_admin_list(self) -> List[str]:
|
||||
return await self.cache.get_all()
|
||||
|
||||
async def get_role(
|
||||
self, rid: Optional[int] = None, key: Optional[str] = None
|
||||
@ -133,7 +144,7 @@ class UserRoleServices(AsyncInitializingComponent):
|
||||
ptype: Optional[str] = None,
|
||||
v0: Optional[str] = None,
|
||||
v1: Optional[str] = None,
|
||||
) -> Optional[RoleModel]:
|
||||
) -> Sequence[CasbinRule]:
|
||||
return await self.repo.get_role_rule(ptype, v0, v1)
|
||||
|
||||
async def is_user_in_role_group(
|
||||
|
Loading…
Reference in New Issue
Block a user