sa_token_core/stp_interface.rs
1// Author: 金书记 | Author: Jin Shuji
2//
3//! Permission / Role / Ban Data Source | 权限、角色、封禁数据源
4//!
5//! Application-supplied permission / role data source (DB, RPC, config, …).
6//! 由业务方实现的权限/角色数据源(数据库、RPC、配置中心……)。
7//! This crate adds [`StpInterface::is_writable`] to answer where write ops land.
8//! 本 crate 额外提供 [`StpInterface::is_writable`],标明写操作落点。
9//!
10//! The application implements it to plug a data
11//! source (database, RPC, config service, ...) into the framework.
12//! [`StpInterface::is_writable`] answers: **where should framework-issued writes land?**
13//!
14//! ## 唯一数据源 | Single Data Source
15//!
16//! B2 起,本 trait 是权限/角色/封禁数据的**唯一**抽象:
17//! - 未注入自定义实现时,框架使用 [`StorageStpInterface`](读写都走 storage)
18//! - 注入后,**读**走回调;**写**按 [`crate::config::GrantWritePolicy`] 处理
19//! - 优先级判断**只存在于** [`crate::service::AuthzService`] 一处,
20//! `GrantRepo` 不再感知本 trait
21//!
22//! Since B2 this trait is the single abstraction for grant data. Without a
23//! custom implementation the framework uses `StorageStpInterface`. With one,
24//! reads go to the callback while writes follow `GrantWritePolicy`. The
25//! precedence decision lives **only** in `AuthzService`; `GrantRepo` is
26//! deliberately unaware of this trait to avoid recursing through
27//! `StorageStpInterface`.
28
29mod storage;
30
31use async_trait::async_trait;
32
33pub use storage::StorageStpInterface;
34
35use crate::error::SaTokenResult;
36
37/// 权限、角色、封禁数据回调 | Permission, role and ban data callback
38#[async_trait]
39pub trait StpInterface: Send + Sync {
40 /// 返回账号在指定体系下的权限列表 | Permission list for the account in a login type
41 async fn get_permission_list(
42 &self,
43 login_id: &str,
44 login_type: &str,
45 ) -> SaTokenResult<Vec<String>>;
46
47 /// 返回账号在指定体系下的角色列表 | Role list for the account in a login type
48 async fn get_role_list(&self, login_id: &str, login_type: &str) -> SaTokenResult<Vec<String>>;
49
50 /// 返回封禁等级;`None` 表示未封禁。
51 ///
52 /// 仅在 storage 中**查不到**封禁记录时才会被调用,
53 /// 因此实现方无需关心与 storage 的优先级。
54 ///
55 /// Ban level, `None` when not banned. Only consulted when storage has no ban
56 /// record, so implementors need not reason about precedence.
57 async fn is_disabled(&self, login_id: &str, service: &str) -> SaTokenResult<Option<i32>> {
58 let _ = (login_id, service);
59 Ok(None)
60 }
61
62 /// 本数据源是否接受框架发起的**写入**。
63 ///
64 /// 默认 `false`(只读),因为绝大多数自定义实现是「从既有权限系统读」,
65 /// 把权限写回去需要额外的表结构与事务语义。返回 `false` 时,框架的
66 /// `set_permissions` / `add_role` 等写操作会按
67 /// [`crate::config::GrantWritePolicy`] 告警或拒绝,
68 /// **避免写进一个自己永远读不到的地方**。
69 ///
70 /// 内置的 [`StorageStpInterface`] 返回 `true`,因为它的读写同源。
71 ///
72 /// Whether this data source accepts framework-issued writes. Defaults to
73 /// `false` (read-only). The built-in `StorageStpInterface` returns `true`
74 /// since its reads and writes share the same storage.
75 fn is_writable(&self) -> bool {
76 false
77 }
78}