Skip to main content

sz_orm_auth/
lib.rs

1//! # SZ-ORM Auth — Authentication & Authorization
2//!
3//! Provides JWT token signing/verification and RBAC-based permission control (`Authorizer`/`RbacAuthorizer`),
4//! covering user, credential, and role-permission models.
5//!
6//! ## Main Modules
7//!
8//! - [`auth`] — User, credential and other basic models
9//! - [`jwt`] — JSON Web Token signing and verification
10//! - [`authorizer`] — RBAC authorizer (with role hierarchy)
11//! - [`oauth2`] — OAuth2 authorization code flow (RFC 6749)
12//! - [`mfa`] — Multi-factor authentication (TOTP, RFC 6238)
13//! - [`token_store`] — Refresh token storage (rotation + revocation + replay detection)
14
15pub mod auth;
16pub mod authorizer;
17pub mod error;
18pub mod jwt;
19pub mod mfa;
20pub mod oauth2;
21pub mod token_store;
22
23pub use auth::*;
24pub use authorizer::{Authorizer, RbacAuthorizer};
25pub use error::AuthError;
26pub use mfa::{MfaManager, MfaSecret, TotpVerifier};
27pub use oauth2::{AuthorizationCode, AuthorizationRequest, OAuth2Server, TokenRequest};
28pub use token_store::{StoredToken, TokenFamilyError, TokenStore};
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    /// Test password verifier (after H-1 fix, authenticate must configure verifier)
35    struct MockVerifier;
36    impl auth::PasswordVerifier for MockVerifier {
37        fn verify_password(&self, _u: &str, _p: &str) -> Result<i64, AuthError> {
38            Ok(42)
39        }
40    }
41
42    #[test]
43    fn test_module_exports() {
44        // Smoke test ensuring the public API compiles and is reachable.
45        let creds = Credentials::new("user", "pass");
46        assert_eq!(creds.username, "user");
47    }
48
49    #[test]
50    fn test_rbac_authorizer_via_lib_root() {
51        let authorizer = RbacAuthorizer::new();
52        // v4.8.0 修复 M-11:action 级权限不再隐式授予任意资源
53        let user = User::new(1, "user").with_permissions(vec!["read".to_string()]);
54        let can_read = authorizer.can(&user, "read", "resource");
55        assert!(!can_read.unwrap(), "action 级 read 不得授予 read:resource");
56
57        // 显式 action:resource 权限正常放行
58        let user2 = User::new(2, "user").with_permissions(vec!["read:resource".to_string()]);
59        let can_read = authorizer.can(&user2, "read", "resource");
60        let can_delete = authorizer.can(&user2, "delete", "resource");
61        assert!(can_read.unwrap());
62        assert!(!can_delete.unwrap());
63    }
64
65    #[test]
66    fn test_rbac_authorizer_admin_via_lib_root() {
67        let authorizer = RbacAuthorizer::new();
68        let user = User::new(1, "admin").with_roles(vec!["admin".to_string()]);
69
70        let can_do_anything = authorizer.can(&user, "delete", "anything");
71
72        assert!(can_do_anything.unwrap());
73    }
74
75    #[test]
76    fn test_jwt_authenticator_via_lib_root() {
77        // v1.2.1 H-1 修复:authenticate 必须配置 password_verifier
78        let auth = JwtAuthenticator::new("secret", "issuer", 3600)
79            .with_password_verifier(std::sync::Arc::new(MockVerifier));
80        let creds = Credentials::new("user", "pass");
81
82        let token = auth.authenticate(&creds).expect("authenticate");
83        assert!(!token.access_token.is_empty());
84
85        let user = auth.verify_token(&token.access_token).expect("verify");
86        assert_eq!(user.username, "user");
87        assert_eq!(user.id, 42);
88    }
89
90    #[test]
91    fn test_jwt_encoder_via_lib_root() {
92        use jwt::{JwtClaims, JwtEncoder};
93        let encoder = JwtEncoder::new("lib-secret");
94        let claims = JwtClaims::new("lib-user", 9_999_999_999);
95        let token = encoder.encode(&claims).expect("encode");
96        let decoded = encoder.decode(&token).expect("decode");
97        assert_eq!(decoded.sub, "lib-user");
98    }
99}